// Path: src/test/java/com/statemachinesystems/envy/common/StubConfigSource.java
// public class StubConfigSource implements ConfigSource {
// 
//     private final Map<Parameter, String> params;
// 
//     public StubConfigSource() {
//         this.params = new HashMap<Parameter, String>();
//     }
// 
//     public StubConfigSource add(String parameter, String value) {
//         params.put(new Parameter(parameter), value);
//         return this;
//     }
// 
//     @Override
//     public String getValue(Parameter parameter) {
//         return params.get(parameter);
//     }
// }
// 
// Path: src/main/java/com/statemachinesystems/envy/parsers/IntegerValueParser.java
// public class IntegerValueParser implements ValueParser<Integer> {
// 
//     @Override
//     public Integer parseValue(String value) {
//         return Integer.parseInt(value);
//     }
// 
//     @Override
//     public Class<Integer> getValueClass() {
//         return Integer.class;
//     }
// 
// }
// 
// Path: src/main/java/com/statemachinesystems/envy/parsers/ObjectAsStringValueParser.java
// public class ObjectAsStringValueParser implements ValueParser<Object> {
// 
//     private final StringValueParser valueParser = new StringValueParser();
// 
//     @Override
//     public Object parseValue(String value) {
//         return valueParser.parseValue(value);
//     }
// 
//     @Override
//     public Class<Object> getValueClass() {
//         return Object.class;
//     }
// }
// 
// Path: src/main/java/com/statemachinesystems/envy/parsers/StringValueParser.java
// public class StringValueParser implements ValueParser<String> {
// 
//     @Override
//     public String parseValue(String value) {
//         return value;
//     }
// 
//     @Override
//     public Class<String> getValueClass() {
//         return String.class;
//     }
// }
// 
// Path: src/main/java/com/statemachinesystems/envy/values/ConfigValue.java
// public interface ConfigValue<T> extends Serializable {
// 
//     static <T> ConfigValue<T> of(T value, ConfigValue.Status status, Method method) {
//         return method.getAnnotation(Sensitive.class) != null
//             ? new SensitiveValue<>(value, status)
//             : new ResolvedValue<>(value, status);
//     }
// 
//     enum Status {
//         CONFIGURED,
//         MISSING,
//         DEFAULTED
//     }
// 
//     /**
//      * Returns the fully extracted and parsed value, or a default.
//      *
//      * @param proxy  the proxy this value belongs to
//      */
//     T getValue(Object proxy);
// 
//     /**
//      * Returns the value formatted as a String.
//      *
//      * @param proxy  the proxy this value belongs to
//      * @return  the value formatted as a String
//      */
//     String format(Object proxy);
// 
//     /**
//      * Indicates whether the value was found in the underlying {@link ConfigSource},
//      * missing, or replaced by a default value.
//      */
//     Status getStatus();
// }
// 
// Path: src/main/java/com/statemachinesystems/envy/values/ConfigValue.java
// enum Status {
//     CONFIGURED,
//     MISSING,
//     DEFAULTED
// }


import com.statemachinesystems.envy.common.StubConfigSource;
import com.statemachinesystems.envy.parsers.IntegerValueParser;
import com.statemachinesystems.envy.parsers.ObjectAsStringValueParser;
import com.statemachinesystems.envy.parsers.StringValueParser;
import com.statemachinesystems.envy.values.ConfigValue;
import com.statemachinesystems.envy.values.ConfigValue.Status;
import org.junit.Before;
import org.junit.Test;
import static org.junit.Assert.*;
    }

    @Test(expected = IllegalArgumentException.class)
    public void voidReturnTypesAreRejected() {
        StubConfigSource configSource = new StubConfigSource().add("method.with.void.return.type", "bad");
        ValueParserFactory valueParserFactory = new ValueParserFactory(new ValueParser<Void>() {
            @Override
            public Void parseValue(String value) {
                return null;
            }

            @Override
            public Class<Void> getValueClass() {
                return Void.class;
            }
        });
        ConfigExtractor configExtractor = new ConfigExtractor(valueParserFactory, configSource);
        configExtractor.extractConfigMap(BadConfigWithVoidReturnType.class);
    }

    @Test
    public void mapKeysAreOrderedAlphabetically() {
        String previousKey = "";
        for (String methodName : configExtractor.extractConfigMap(ExampleConfig.class).getMethodNames()) {
            assertTrue(previousKey.compareTo(methodName) <= 0);
            previousKey = methodName;
        }
    }

    private Object getValue(String methodName, Status expectedStatus) {
// Path: src/test/java/com/statemachinesystems/envy/common/StubConfigSource.java
// public class StubConfigSource implements ConfigSource {
// 
//     private final Map<Parameter, String> params;
// 
//     public StubConfigSource() {
//         this.params = new HashMap<Parameter, String>();
//     }
// 
//     public StubConfigSource add(String parameter, String value) {
//         params.put(new Parameter(parameter), value);
//         return this;
//     }
// 
//     @Override
//     public String getValue(Parameter parameter) {
//         return params.get(parameter);
//     }
// }
// 
// Path: src/main/java/com/statemachinesystems/envy/parsers/IntegerValueParser.java
// public class IntegerValueParser implements ValueParser<Integer> {
// 
//     @Override
//     public Integer parseValue(String value) {
//         return Integer.parseInt(value);
//     }
// 
//     @Override
//     public Class<Integer> getValueClass() {
//         return Integer.class;
//     }
// 
// }
// 
// Path: src/main/java/com/statemachinesystems/envy/parsers/ObjectAsStringValueParser.java
// public class ObjectAsStringValueParser implements ValueParser<Object> {
// 
//     private final StringValueParser valueParser = new StringValueParser();
// 
//     @Override
//     public Object parseValue(String value) {
//         return valueParser.parseValue(value);
//     }
// 
//     @Override
//     public Class<Object> getValueClass() {
//         return Object.class;
//     }
// }
// 
// Path: src/main/java/com/statemachinesystems/envy/parsers/StringValueParser.java
// public class StringValueParser implements ValueParser<String> {
// 
//     @Override
//     public String parseValue(String value) {
//         return value;
//     }
// 
//     @Override
//     public Class<String> getValueClass() {
//         return String.class;
//     }
// }
// 
// Path: src/main/java/com/statemachinesystems/envy/values/ConfigValue.java
// public interface ConfigValue<T> extends Serializable {
// 
//     static <T> ConfigValue<T> of(T value, ConfigValue.Status status, Method method) {
//         return method.getAnnotation(Sensitive.class) != null
//             ? new SensitiveValue<>(value, status)
//             : new ResolvedValue<>(value, status);
//     }
// 
//     enum Status {
//         CONFIGURED,
//         MISSING,
//         DEFAULTED
//     }
// 
//     /**
//      * Returns the fully extracted and parsed value, or a default.
//      *
//      * @param proxy  the proxy this value belongs to
//      */
//     T getValue(Object proxy);
// 
//     /**
//      * Returns the value formatted as a String.
//      *
//      * @param proxy  the proxy this value belongs to
//      * @return  the value formatted as a String
//      */
//     String format(Object proxy);
// 
//     /**
//      * Indicates whether the value was found in the underlying {@link ConfigSource},
//      * missing, or replaced by a default value.
//      */
//     Status getStatus();
// }
// 
// Path: src/main/java/com/statemachinesystems/envy/values/ConfigValue.java
// enum Status {
//     CONFIGURED,
//     MISSING,
//     DEFAULTED
// }


// Path: src/test/java/com/statemachinesystems/envy/ConfigExtractorTest.java
import com.statemachinesystems.envy.common.StubConfigSource;
import com.statemachinesystems.envy.parsers.IntegerValueParser;
import com.statemachinesystems.envy.parsers.ObjectAsStringValueParser;
import com.statemachinesystems.envy.parsers.StringValueParser;
import com.statemachinesystems.envy.values.ConfigValue;
import com.statemachinesystems.envy.values.ConfigValue.Status;
import org.junit.Before;
import org.junit.Test;
import static org.junit.Assert.*;

    }

    @Test(expected = IllegalArgumentException.class)
    public void voidReturnTypesAreRejected() {
        StubConfigSource configSource = new StubConfigSource().add("method.with.void.return.type", "bad");
        ValueParserFactory valueParserFactory = new ValueParserFactory(new ValueParser<Void>() {
            @Override
            public Void parseValue(String value) {
                return null;
            }

            @Override
            public Class<Void> getValueClass() {
                return Void.class;
            }
        });
        ConfigExtractor configExtractor = new ConfigExtractor(valueParserFactory, configSource);
        configExtractor.extractConfigMap(BadConfigWithVoidReturnType.class);
    }

    @Test
    public void mapKeysAreOrderedAlphabetically() {
        String previousKey = "";
        for (String methodName : configExtractor.extractConfigMap(ExampleConfig.class).getMethodNames()) {
            assertTrue(previousKey.compareTo(methodName) <= 0);
            previousKey = methodName;
        }
    }

    private Object getValue(String methodName, Status expectedStatus) {
        ConfigValue configValue = configExtractor.extractConfigMap(ExampleConfig.class).getValue(methodName);