Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

chore: fix jacoco coverage minimum, throw in memory provider #561

Merged
merged 1 commit into from
Aug 16, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package dev.openfeature.sdk.exceptions;

import dev.openfeature.sdk.ErrorCode;
import lombok.Getter;
import lombok.experimental.StandardException;

@SuppressWarnings("checkstyle:MissingJavadocType")
@StandardException
public class ProviderNotReadyError extends OpenFeatureError {
private static final long serialVersionUID = 1L;
@Getter private final ErrorCode errorCode = ErrorCode.PROVIDER_NOT_READY;
}
Original file line number Diff line number Diff line change
@@ -1,26 +1,29 @@
package dev.openfeature.sdk.providers.memory;

import dev.openfeature.sdk.Value;
import dev.openfeature.sdk.Metadata;
import dev.openfeature.sdk.EventProvider;
import dev.openfeature.sdk.ProviderState;
import dev.openfeature.sdk.ProviderEventDetails;
import dev.openfeature.sdk.ErrorCode;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;

import dev.openfeature.sdk.EvaluationContext;
import dev.openfeature.sdk.EventProvider;
import dev.openfeature.sdk.Metadata;
import dev.openfeature.sdk.ProviderEvaluation;
import dev.openfeature.sdk.ProviderEventDetails;
import dev.openfeature.sdk.ProviderState;
import dev.openfeature.sdk.Reason;
import dev.openfeature.sdk.Value;
import dev.openfeature.sdk.exceptions.FlagNotFoundError;
import dev.openfeature.sdk.exceptions.GeneralError;
import dev.openfeature.sdk.exceptions.OpenFeatureError;
import dev.openfeature.sdk.exceptions.ProviderNotReadyError;
import dev.openfeature.sdk.exceptions.TypeMismatchError;
import lombok.Getter;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;

import java.util.Map;
import java.util.HashMap;
import java.util.Set;
import java.util.HashSet;
import java.util.Arrays;
import java.util.ArrayList;

/**
* In-memory provider.
*/
Expand Down Expand Up @@ -87,68 +90,52 @@
@Override
public ProviderEvaluation<Boolean> getBooleanEvaluation(String key, Boolean defaultValue,
EvaluationContext evaluationContext) {
return getEvaluation(key, defaultValue, evaluationContext, Boolean.class);
return getEvaluation(key, evaluationContext, Boolean.class);
}

@Override
public ProviderEvaluation<String> getStringEvaluation(String key, String defaultValue,
EvaluationContext evaluationContext) {
return getEvaluation(key, defaultValue, evaluationContext, String.class);
return getEvaluation(key, evaluationContext, String.class);
}

@Override
public ProviderEvaluation<Integer> getIntegerEvaluation(String key, Integer defaultValue,
EvaluationContext evaluationContext) {
return getEvaluation(key, defaultValue, evaluationContext, Integer.class);
return getEvaluation(key, evaluationContext, Integer.class);
}

@Override
public ProviderEvaluation<Double> getDoubleEvaluation(String key, Double defaultValue,
EvaluationContext evaluationContext) {
return getEvaluation(key, defaultValue, evaluationContext, Double.class);
return getEvaluation(key, evaluationContext, Double.class);
}

@SneakyThrows

Check warning on line 114 in src/main/java/dev/openfeature/sdk/providers/memory/InMemoryProvider.java

View check run for this annotation

Codecov / codecov/patch

src/main/java/dev/openfeature/sdk/providers/memory/InMemoryProvider.java#L114

Added line #L114 was not covered by tests
@Override
public ProviderEvaluation<Value> getObjectEvaluation(String key, Value defaultValue,
EvaluationContext evaluationContext) {
return getEvaluation(key, defaultValue, evaluationContext, Value.class);
return getEvaluation(key, evaluationContext, Value.class);
}

private <T> ProviderEvaluation<T> getEvaluation(
String key, T defaultValue, EvaluationContext evaluationContext, Class<?> expectedType
String key, EvaluationContext evaluationContext, Class<?> expectedType
) throws OpenFeatureError {
if (!ProviderState.READY.equals(state)) {
ErrorCode errorCode = ErrorCode.PROVIDER_NOT_READY;
if (ProviderState.ERROR.equals(state)) {
errorCode = ErrorCode.GENERAL;
if (ProviderState.NOT_READY.equals(state)) {
throw new ProviderNotReadyError("provider not yet initialized");

Check warning on line 126 in src/main/java/dev/openfeature/sdk/providers/memory/InMemoryProvider.java

View check run for this annotation

Codecov / codecov/patch

src/main/java/dev/openfeature/sdk/providers/memory/InMemoryProvider.java#L126

Added line #L126 was not covered by tests
Copy link
Member Author

@toddbaert toddbaert Aug 15, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@liran2000 throwing like this ends in the same result, but it's a bit easier to trace, and also simpler to write. This is how we generally recommend it's done. There is a small performance cost in serialization of the exception, but I think it's worth it.

}
return ProviderEvaluation.<T>builder()
.errorCode(errorCode)
.reason(errorCode.name())
.value(defaultValue)
.build();
throw new GeneralError("unknown error");

Check warning on line 128 in src/main/java/dev/openfeature/sdk/providers/memory/InMemoryProvider.java

View check run for this annotation

Codecov / codecov/patch

src/main/java/dev/openfeature/sdk/providers/memory/InMemoryProvider.java#L128

Added line #L128 was not covered by tests
}
Flag<?> flag = flags.get(key);
if (flag == null) {
return ProviderEvaluation.<T>builder()
.value(defaultValue)
.reason(Reason.ERROR.toString())
.errorMessage(ErrorCode.FLAG_NOT_FOUND.name())
.errorCode(ErrorCode.FLAG_NOT_FOUND)
.build();
throw new FlagNotFoundError("flag " + key + "not found");
}
T value;
if (flag.getContextEvaluator() != null) {
value = (T) flag.getContextEvaluator().evaluate(flag, evaluationContext);
} else if (!expectedType.isInstance(flag.getVariants().get(flag.getDefaultVariant()))) {
return ProviderEvaluation.<T>builder()
.value(defaultValue)
.variant(flag.getDefaultVariant())
.reason(Reason.ERROR.toString())
.errorMessage(ErrorCode.TYPE_MISMATCH.name())
.errorCode(ErrorCode.TYPE_MISMATCH)
.build();
throw new TypeMismatchError("flag " + key + "is not of expected type");
} else {
value = (T) flag.getVariants().get(flag.getDefaultVariant());
}
Expand Down
2 changes: 0 additions & 2 deletions src/test/java/dev/openfeature/sdk/e2e/StepDefinitions.java
Original file line number Diff line number Diff line change
Expand Up @@ -271,7 +271,6 @@ public void then_the_default_string_value_should_be_returned() {
@Then("the reason should indicate an error and the error code should indicate a missing flag with {string}")
public void the_reason_should_indicate_an_error_and_the_error_code_should_be_flag_not_found(String errorCode) {
assertEquals(Reason.ERROR.toString(), notFoundDetails.getReason());
assertTrue(notFoundDetails.getErrorMessage().contains(errorCode));
assertTrue(notFoundDetails.getErrorCode().name().equals(errorCode));
}

Expand All @@ -292,7 +291,6 @@ public void then_the_default_integer_value_should_be_returned() {
@Then("the reason should indicate an error and the error code should indicate a type mismatch with {string}")
public void the_reason_should_indicate_an_error_and_the_error_code_should_be_type_mismatch(String errorCode) {
assertEquals(Reason.ERROR.toString(), typeErrorDetails.getReason());
assertTrue(typeErrorDetails.getErrorMessage().contains(errorCode));
assertTrue(typeErrorDetails.getErrorCode().name().equals(errorCode));
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,17 +2,22 @@

import com.google.common.collect.ImmutableMap;
import dev.openfeature.sdk.Client;
import dev.openfeature.sdk.ImmutableContext;
import dev.openfeature.sdk.OpenFeatureAPI;
import dev.openfeature.sdk.Value;
import dev.openfeature.sdk.exceptions.FlagNotFoundError;
import dev.openfeature.sdk.exceptions.TypeMismatchError;
import lombok.SneakyThrows;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test;
import org.omg.CORBA.DynAnyPackage.TypeMismatch;

import java.util.Map;

import static dev.openfeature.sdk.Structure.mapToStructure;
import static dev.openfeature.sdk.testutils.TestFlagsUtils.buildFlags;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertThrows;
import static org.junit.jupiter.api.Assertions.assertTrue;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.spy;
Expand Down Expand Up @@ -81,4 +86,17 @@ void getObjectEvaluation() {
assertEquals(expectedObject, client.getObjectValue("object-flag", new Value(true)));
}

@Test
void notFound() {
assertThrows(FlagNotFoundError.class, () -> {
provider.getBooleanEvaluation("not-found-flag", false, new ImmutableContext());
});
}

@Test
void typeMismatch() {
assertThrows(TypeMismatchError.class, () -> {
provider.getBooleanEvaluation("string-flag", false, new ImmutableContext());
});
}
Comment on lines +89 to +101
Copy link
Member Author

@toddbaert toddbaert Aug 15, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These bring coverage of the new package up to 80%+ to fix the failure in main.

}
Loading