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

refactor: storage tests should use a single test store and base #380

Merged
merged 2 commits into from
Jul 9, 2024
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
55 changes: 55 additions & 0 deletions momento-sdk/src/intTest/java/momento/sdk/BaseStorageTestClass.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
package momento.sdk;

import java.time.Duration;
import java.util.UUID;
import momento.sdk.auth.CredentialProvider;
import momento.sdk.config.StorageConfigurations;
import momento.sdk.responses.storage.CreateStoreResponse;
import momento.sdk.responses.storage.DeleteStoreResponse;
import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.api.BeforeAll;

public class BaseStorageTestClass {
protected static final Duration TEN_SECONDS = Duration.ofSeconds(10);
protected static CredentialProvider credentialProvider;
protected static PreviewStorageClient storageClient;
protected static String storeName;

@BeforeAll
static void beforeAll() {
credentialProvider = CredentialProvider.fromEnvVar("TEST_AUTH_TOKEN");
malandis marked this conversation as resolved.
Show resolved Hide resolved
storageClient =
new PreviewStorageClientBuilder()
.withCredentialProvider(credentialProvider)
.withConfiguration(StorageConfigurations.Laptop.latest())
.build();
storeName = testStoreName();
ensureTestStoreExists(storeName);
}

@AfterAll
static void afterAll() {
cleanupTestStore(storeName);
storageClient.close();
}

protected static void ensureTestStoreExists(String storeName) {
CreateStoreResponse response = storageClient.createStore(storeName).join();
if (response instanceof CreateStoreResponse.Error) {
throw new RuntimeException(
"Failed to test create store: " + ((CreateStoreResponse.Error) response).getMessage());
}
}

public static void cleanupTestStore(String storeName) {
DeleteStoreResponse response = storageClient.deleteStore(storeName).join();
if (response instanceof DeleteStoreResponse.Error) {
throw new RuntimeException(
"Failed to test delete store: " + ((DeleteStoreResponse.Error) response).getMessage());
}
}

public static String testStoreName() {
return "java-integration-test-default-" + UUID.randomUUID();
}
}
69 changes: 22 additions & 47 deletions momento-sdk/src/intTest/java/momento/sdk/storage/ControlTests.java
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,7 @@
import static momento.sdk.TestUtils.randomString;
import static org.assertj.core.api.Assertions.assertThat;

import java.time.Duration;
import momento.sdk.BaseTestClass;
import momento.sdk.BaseStorageTestClass;
import momento.sdk.PreviewStorageClient;
import momento.sdk.auth.CredentialProvider;
import momento.sdk.config.StorageConfigurations;
Expand All @@ -16,45 +15,21 @@
import momento.sdk.responses.storage.DeleteStoreResponse;
import momento.sdk.responses.storage.ListStoresResponse;
import org.assertj.core.api.InstanceOfAssertFactories;
import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test;

public class ControlTests extends BaseTestClass {
private static PreviewStorageClient client;

public static final Duration TEN_SECONDS = Duration.ofSeconds(10);

@BeforeAll
static void setup() {
client =
new PreviewStorageClient(
CredentialProvider.fromEnvVar("MOMENTO_API_KEY"),
StorageConfigurations.Laptop.latest());

// TODO re-using this name
client.createStore(System.getenv("TEST_CACHE_NAME")).join();
}

@AfterAll
static void tearDown() {
client.close();
}

public class ControlTests extends BaseStorageTestClass {
@Test
public void returnsAlreadyExistsWhenCreatingExistingStore() {
// TODO externalize this
// TODO rename env var to something broader like TEST_RESOURCE_NAME
final String existingStore = System.getenv("TEST_CACHE_NAME");
final String existingStore = storeName;

assertThat(client.createStore(existingStore))
assertThat(storageClient.createStore(existingStore))
.succeedsWithin(TEN_SECONDS)
.asInstanceOf(InstanceOfAssertFactories.type(CreateStoreResponse.AlreadyExists.class));
}

@Test
public void returnsNotFoundWhenDeletingUnknownStore() {
assertThat(client.deleteStore(randomString("name")))
assertThat(storageClient.deleteStore(randomString("name")))
.succeedsWithin(TEN_SECONDS)
.asInstanceOf(InstanceOfAssertFactories.type(DeleteStoreResponse.Error.class))
.satisfies(error -> assertThat(error).hasCauseInstanceOf(StoreNotFoundException.class));
Expand All @@ -64,45 +39,45 @@ public void returnsNotFoundWhenDeletingUnknownStore() {
public void listsStoresHappyPath() {
final String storeName = randomString("name");

assertThat(client.createStore(storeName))
assertThat(storageClient.createStore(storeName))
.succeedsWithin(TEN_SECONDS)
.isInstanceOf(CreateStoreResponse.Success.class);

try {
assertThat(client.listStores())
assertThat(storageClient.listStores())
.succeedsWithin(TEN_SECONDS)
.asInstanceOf(InstanceOfAssertFactories.type(ListStoresResponse.Success.class))
.satisfies(
success ->
assertThat(success.getStores())
.anyMatch(storeInfo -> storeInfo.getName().equals(storeName)));

final ListStoresResponse response = client.listStores().join();
final ListStoresResponse response = storageClient.listStores().join();
assertThat(response).isInstanceOf(ListStoresResponse.Success.class);
} finally {
// cleanup
assertThat(client.deleteStore(storeName))
assertThat(storageClient.deleteStore(storeName))
.succeedsWithin(TEN_SECONDS)
.isInstanceOf(DeleteStoreResponse.Success.class);
}
}

@Test
public void returnsBadRequestForEmptyStoreName() {
assertThat(client.createStore(" "))
assertThat(storageClient.createStore(" "))
.succeedsWithin(TEN_SECONDS)
.asInstanceOf(InstanceOfAssertFactories.type(CreateStoreResponse.Error.class))
.satisfies(error -> assertThat(error).hasCauseInstanceOf(BadRequestException.class));
}

@Test
public void throwsValidationExceptionForNullStoreName() {
assertThat(client.createStore(null))
assertThat(storageClient.createStore(null))
.succeedsWithin(TEN_SECONDS)
.asInstanceOf(InstanceOfAssertFactories.type(CreateStoreResponse.Error.class))
.satisfies(error -> assertThat(error).hasCauseInstanceOf(InvalidArgumentException.class));

assertThat(client.deleteStore(null))
assertThat(storageClient.deleteStore(null))
.succeedsWithin(TEN_SECONDS)
.asInstanceOf(InstanceOfAssertFactories.type(DeleteStoreResponse.Error.class))
.satisfies(error -> assertThat(error).hasCauseInstanceOf(InvalidArgumentException.class));
Expand All @@ -113,25 +88,25 @@ public void deleteSucceeds() {
final String storeName = randomString("name");

try {
assertThat(client.createStore(storeName))
assertThat(storageClient.createStore(storeName))
.succeedsWithin(TEN_SECONDS)
.isInstanceOf(CreateStoreResponse.Success.class);

assertThat(client.createStore(storeName))
assertThat(storageClient.createStore(storeName))
.succeedsWithin(TEN_SECONDS)
.asInstanceOf(InstanceOfAssertFactories.type(CreateStoreResponse.AlreadyExists.class));

assertThat(client.deleteStore(storeName))
assertThat(storageClient.deleteStore(storeName))
.succeedsWithin(TEN_SECONDS)
.isInstanceOf(DeleteStoreResponse.Success.class);

assertThat(client.deleteStore(storeName))
assertThat(storageClient.deleteStore(storeName))
.succeedsWithin(TEN_SECONDS)
.asInstanceOf(InstanceOfAssertFactories.type(DeleteStoreResponse.Error.class))
.satisfies(error -> assertThat(error).hasCauseInstanceOf(StoreNotFoundException.class));
} finally {
// Just in case the second create or delete fails
client.deleteStore(storeName).join();
storageClient.deleteStore(storeName).join();
}
}

Expand All @@ -144,23 +119,23 @@ public void returnsErrorForBadToken() {
+ "s76573jnajhjjjhjdhnndy";
final CredentialProvider badTokenProvider = CredentialProvider.fromString(badToken);

try (final PreviewStorageClient client =
try (final PreviewStorageClient storageClient =
new PreviewStorageClient(
CredentialProvider.fromString(badToken),
StorageConfigurations.Laptop.latest()) /*CacheClient.builder(
StorageConfigurations.Laptop.latest()) /*CacheStorageClient.builder(
badTokenProvider, Configurations.Laptop.latest(), Duration.ofSeconds(10))
.build()*/) {
assertThat(client.createStore(storeName))
assertThat(storageClient.createStore(storeName))
.succeedsWithin(TEN_SECONDS)
.asInstanceOf(InstanceOfAssertFactories.type(CreateStoreResponse.Error.class))
.satisfies(error -> assertThat(error).hasCauseInstanceOf(AuthenticationException.class));

assertThat(client.deleteStore(storeName))
assertThat(storageClient.deleteStore(storeName))
.succeedsWithin(TEN_SECONDS)
.asInstanceOf(InstanceOfAssertFactories.type(DeleteStoreResponse.Error.class))
.satisfies(error -> assertThat(error).hasCauseInstanceOf(AuthenticationException.class));

assertThat(client.listStores())
assertThat(storageClient.listStores())
.succeedsWithin(TEN_SECONDS)
.asInstanceOf(InstanceOfAssertFactories.type(ListStoresResponse.Error.class))
.satisfies(error -> assertThat(error).hasCauseInstanceOf(AuthenticationException.class));
Expand Down
66 changes: 20 additions & 46 deletions momento-sdk/src/intTest/java/momento/sdk/storage/DataTests.java
Original file line number Diff line number Diff line change
Expand Up @@ -4,52 +4,26 @@
import static org.assertj.core.api.AssertionsForClassTypes.assertThat;
import static org.junit.jupiter.api.Assertions.assertThrows;

import momento.sdk.BaseTestClass;
import momento.sdk.PreviewStorageClient;
import momento.sdk.auth.CredentialProvider;
import momento.sdk.config.StorageConfigurations;
import momento.sdk.BaseStorageTestClass;
import momento.sdk.exceptions.ClientSdkException;
import momento.sdk.exceptions.StoreNotFoundException;
import momento.sdk.responses.storage.DeleteResponse;
import momento.sdk.responses.storage.GetResponse;
import momento.sdk.responses.storage.PutResponse;
import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test;

public class DataTests extends BaseTestClass {
private static PreviewStorageClient client;

// TODO can set to the same value as the cache tests
// TODO rename env var for clarity to TEST_RESOURCE_NAME or similar
private final String storeName = System.getenv("TEST_CACHE_NAME");

@BeforeAll
static void setup() {
client =
new PreviewStorageClient(
CredentialProvider.fromEnvVar("MOMENTO_API_KEY"),
StorageConfigurations.Laptop.latest());

client.createStore(System.getenv("TEST_CACHE_NAME")).join();
}

@AfterAll
static void tearDown() {
client.close();
}

public class DataTests extends BaseStorageTestClass {
@Test
void getReturnsValueAsStringAfterPut() {
final String key = randomString("key");
final String value = randomString("value");

// Successful Set
final PutResponse putResponse = client.put(storeName, key, value).join();
final PutResponse putResponse = storageClient.put(storeName, key, value).join();
assertThat(putResponse).isInstanceOf(PutResponse.Success.class);

// Successful Get
final GetResponse getResponse = client.get(storeName, key).join();
final GetResponse getResponse = storageClient.get(storeName, key).join();
assertThat(getResponse).isInstanceOf(GetResponse.Found.class);
assertThat(getResponse.valueWhenFound().get().getString().get()).isEqualTo(value);
}
Expand All @@ -60,11 +34,11 @@ void getReturnsValueAsByteArrayAfterPut() {
final String value = randomString("value");

// Successful Set
final PutResponse putResponse = client.put(storeName, key, value.getBytes()).join();
final PutResponse putResponse = storageClient.put(storeName, key, value.getBytes()).join();
assertThat(putResponse).isInstanceOf(PutResponse.Success.class);

// Successful Get
final GetResponse getResponse = client.get(storeName, key).join();
final GetResponse getResponse = storageClient.get(storeName, key).join();
assertThat(getResponse).isInstanceOf(GetResponse.Found.class);
assertThat(getResponse.valueWhenFound().get().getByteArray().get()).isEqualTo(value.getBytes());
}
Expand All @@ -75,11 +49,11 @@ void getReturnsValueAsLongAfterPut() {
final long value = 42L;

// Successful Set
final PutResponse putResponse = client.put(storeName, key, value).join();
final PutResponse putResponse = storageClient.put(storeName, key, value).join();
assertThat(putResponse).isInstanceOf(PutResponse.Success.class);

// Successful Get
final GetResponse getResponse = client.get(storeName, key).join();
final GetResponse getResponse = storageClient.get(storeName, key).join();
assertThat(getResponse).isInstanceOf(GetResponse.Found.class);
assertThat(getResponse.valueWhenFound().get().getLong().get()).isEqualTo(value);
}
Expand All @@ -90,19 +64,19 @@ void getReturnsValueAsDoubleAfterPut() {
final double value = 3.14;

// Successful Set
final PutResponse putResponse = client.put(storeName, key, value).join();
final PutResponse putResponse = storageClient.put(storeName, key, value).join();
assertThat(putResponse).isInstanceOf(PutResponse.Success.class);

// Successful Get
final GetResponse getResponse = client.get(storeName, key).join();
final GetResponse getResponse = storageClient.get(storeName, key).join();
assertThat(getResponse).isInstanceOf(GetResponse.Found.class);
assertThat(getResponse.valueWhenFound().get().getDouble().get()).isEqualTo(value);
}

@Test
void storeKeyNotFound() {
// Get key that was not set
final GetResponse response = client.get(storeName, randomString("key")).join();
final GetResponse response = storageClient.get(storeName, randomString("key")).join();
assertThat(response).isInstanceOf(GetResponse.NotFound.class);
assert response.valueWhenFound().isEmpty();
assert response instanceof GetResponse.NotFound;
Expand All @@ -113,11 +87,11 @@ void storeKeyNotFound() {
public void badStoreNameReturnsError() {
final String storeName = randomString("name");

final GetResponse getResponse = client.get(storeName, "").join();
final GetResponse getResponse = storageClient.get(storeName, "").join();
assertThat(getResponse).isInstanceOf(GetResponse.Error.class);
assertThat(((GetResponse.Error) getResponse)).hasCauseInstanceOf(StoreNotFoundException.class);

final PutResponse putResponse = client.put(storeName, "", "").join();
final PutResponse putResponse = storageClient.put(storeName, "", "").join();
assertThat(putResponse).isInstanceOf(PutResponse.Error.class);
assertThat(((PutResponse.Error) putResponse)).hasCauseInstanceOf(StoreNotFoundException.class);
}
Expand All @@ -126,8 +100,8 @@ public void badStoreNameReturnsError() {
public void allowEmptyKeyValuesOnGet() throws Exception {
final String emptyKey = "";
final String emptyValue = "";
client.put(storeName, emptyKey, emptyValue).get();
final GetResponse response = client.get(storeName, emptyKey).get();
storageClient.put(storeName, emptyKey, emptyValue).get();
final GetResponse response = storageClient.get(storeName, emptyKey).get();
assertThat(response).isInstanceOf(GetResponse.Found.class);
assert response.valueWhenFound().get().getString().get().isEmpty();
}
Expand All @@ -137,15 +111,15 @@ public void deleteHappyPath() throws Exception {
final String key = "key";
final String value = "value";

client.put(storeName, key, value).get();
final GetResponse getResponse = client.get(storeName, key).get();
storageClient.put(storeName, key, value).get();
final GetResponse getResponse = storageClient.get(storeName, key).get();
assertThat(getResponse).isInstanceOf(GetResponse.Found.class);
assertThat(getResponse.valueWhenFound().get().getString().get()).isEqualTo(value);

final DeleteResponse deleteResponse = client.delete(storeName, key).get();
final DeleteResponse deleteResponse = storageClient.delete(storeName, key).get();
assertThat(deleteResponse).isInstanceOf(DeleteResponse.Success.class);

final GetResponse getAfterDeleteResponse = client.get(storeName, key).get();
final GetResponse getAfterDeleteResponse = storageClient.get(storeName, key).get();
assert getAfterDeleteResponse.valueWhenFound().isEmpty();
assert getAfterDeleteResponse instanceof GetResponse.NotFound;
}
Expand All @@ -154,7 +128,7 @@ public void deleteHappyPath() throws Exception {
public void deleteNonExistentKey() throws Exception {
final String key = randomString("key");

final DeleteResponse deleteResponse = client.delete(storeName, key).get();
final DeleteResponse deleteResponse = storageClient.delete(storeName, key).get();
assertThat(deleteResponse).isInstanceOf(DeleteResponse.Success.class);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ public PreviewStorageClientBuilder withConfiguration(
*
* @return the client.
*/
public IPreviewStorageClient build() {
public PreviewStorageClient build() {
Copy link
Contributor Author

Choose a reason for hiding this comment

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

I changed this since PreviewStorageClient is Closeable. In order to both use the builder and explicitly call close on the client, we should return the concrete class.

if (credentialProvider == null) {
credentialProvider = new EnvVarCredentialProvider("MOMENTO_API_KEY");
}
Expand Down
Loading