Add test dependencies for FoundationDB
This commit is contained in:
parent
d6f14d02dd
commit
a99f7bb87d
6
pom.xml
6
pom.xml
|
@ -332,6 +332,12 @@
|
||||||
<type>pom</type>
|
<type>pom</type>
|
||||||
<scope>import</scope>
|
<scope>import</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>earth.adi</groupId>
|
||||||
|
<artifactId>testcontainers-foundationdb</artifactId>
|
||||||
|
<version>1.1.0</version>
|
||||||
|
<scope>test</scope>
|
||||||
|
</dependency>
|
||||||
</dependencies>
|
</dependencies>
|
||||||
</dependencyManagement>
|
</dependencyManagement>
|
||||||
|
|
||||||
|
|
|
@ -502,6 +502,12 @@
|
||||||
<scope>test</scope>
|
<scope>test</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>earth.adi</groupId>
|
||||||
|
<artifactId>testcontainers-foundationdb</artifactId>
|
||||||
|
<scope>test</scope>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>com.google.auth</groupId>
|
<groupId>com.google.auth</groupId>
|
||||||
<artifactId>google-auth-library-oauth2-http</artifactId>
|
<artifactId>google-auth-library-oauth2-http</artifactId>
|
||||||
|
@ -733,6 +739,7 @@
|
||||||
<!-- add-opens: work around PATCH not being a supported method on HttpUrlConnection -->
|
<!-- add-opens: work around PATCH not being a supported method on HttpUrlConnection -->
|
||||||
<argLine>-javaagent:${org.mockito:mockito-core:jar} --add-opens=java.base/java.net=ALL-UNNAMED</argLine>
|
<argLine>-javaagent:${org.mockito:mockito-core:jar} --add-opens=java.base/java.net=ALL-UNNAMED</argLine>
|
||||||
<systemPropertyVariables>
|
<systemPropertyVariables>
|
||||||
|
<foundationdb.version>${foundationdb.version}</foundationdb.version>
|
||||||
<localstackImage>${localstack.image}</localstackImage>
|
<localstackImage>${localstack.image}</localstackImage>
|
||||||
</systemPropertyVariables>
|
</systemPropertyVariables>
|
||||||
</configuration>
|
</configuration>
|
||||||
|
|
|
@ -0,0 +1,19 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2025 Signal Messenger, LLC
|
||||||
|
* SPDX-License-Identifier: AGPL-3.0-only
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.whispersystems.textsecuregcm.storage;
|
||||||
|
|
||||||
|
import com.apple.foundationdb.Database;
|
||||||
|
import com.apple.foundationdb.FDB;
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
|
interface FoundationDbDatabaseLifecycleManager {
|
||||||
|
|
||||||
|
void initializeDatabase(final FDB fdb) throws IOException;
|
||||||
|
|
||||||
|
Database getDatabase();
|
||||||
|
|
||||||
|
void closeDatabase();
|
||||||
|
}
|
|
@ -0,0 +1,43 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2025 Signal Messenger, LLC
|
||||||
|
* SPDX-License-Identifier: AGPL-3.0-only
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.whispersystems.textsecuregcm.storage;
|
||||||
|
|
||||||
|
import com.apple.foundationdb.Database;
|
||||||
|
import com.apple.foundationdb.FDB;
|
||||||
|
import java.io.IOException;
|
||||||
|
import org.junit.jupiter.api.extension.BeforeAllCallback;
|
||||||
|
import org.junit.jupiter.api.extension.ExtensionContext;
|
||||||
|
|
||||||
|
class FoundationDbExtension implements BeforeAllCallback, ExtensionContext.Store.CloseableResource {
|
||||||
|
|
||||||
|
private static FoundationDbDatabaseLifecycleManager databaseLifecycleManager;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void beforeAll(final ExtensionContext context) throws IOException {
|
||||||
|
if (databaseLifecycleManager == null) {
|
||||||
|
final String serviceContainerName = System.getProperty("foundationDb.serviceContainerName");
|
||||||
|
|
||||||
|
databaseLifecycleManager = serviceContainerName != null
|
||||||
|
? new ServiceContainerFoundationDbDatabaseLifecycleManager(serviceContainerName)
|
||||||
|
: new TestcontainersFoundationDbDatabaseLifecycleManager();
|
||||||
|
|
||||||
|
databaseLifecycleManager.initializeDatabase(FDB.selectAPIVersion(730));
|
||||||
|
|
||||||
|
context.getRoot().getStore(ExtensionContext.Namespace.GLOBAL).put(getClass().getName(), this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public Database getDatabase() {
|
||||||
|
return databaseLifecycleManager.getDatabase();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void close() throws Throwable {
|
||||||
|
if (databaseLifecycleManager != null) {
|
||||||
|
databaseLifecycleManager.closeDatabase();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,34 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2025 Signal Messenger, LLC
|
||||||
|
* SPDX-License-Identifier: AGPL-3.0-only
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.whispersystems.textsecuregcm.storage;
|
||||||
|
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
import org.junit.jupiter.api.extension.RegisterExtension;
|
||||||
|
import org.whispersystems.textsecuregcm.util.TestRandomUtil;
|
||||||
|
import java.nio.charset.StandardCharsets;
|
||||||
|
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertArrayEquals;
|
||||||
|
|
||||||
|
public class FoundationDbTest {
|
||||||
|
|
||||||
|
@RegisterExtension
|
||||||
|
static FoundationDbExtension FOUNDATION_DB_EXTENSION = new FoundationDbExtension();
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void setGetValue() {
|
||||||
|
final byte[] key = "test".getBytes(StandardCharsets.UTF_8);
|
||||||
|
final byte[] value = TestRandomUtil.nextBytes(16);
|
||||||
|
|
||||||
|
FOUNDATION_DB_EXTENSION.getDatabase().run(transaction -> {
|
||||||
|
transaction.set(key, value);
|
||||||
|
return null;
|
||||||
|
});
|
||||||
|
|
||||||
|
final byte[] retrievedValue = FOUNDATION_DB_EXTENSION.getDatabase().run(transaction -> transaction.get(key).join());
|
||||||
|
|
||||||
|
assertArrayEquals(value, retrievedValue);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,63 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2025 Signal Messenger, LLC
|
||||||
|
* SPDX-License-Identifier: AGPL-3.0-only
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.whispersystems.textsecuregcm.storage;
|
||||||
|
|
||||||
|
import com.apple.foundationdb.Database;
|
||||||
|
import com.apple.foundationdb.FDB;
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.FileWriter;
|
||||||
|
import java.io.IOException;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Manages the lifecycle of a database connected to a FoundationDB instance running as an external service container.
|
||||||
|
*/
|
||||||
|
class ServiceContainerFoundationDbDatabaseLifecycleManager implements FoundationDbDatabaseLifecycleManager {
|
||||||
|
|
||||||
|
private final String foundationDbServiceContainerName;
|
||||||
|
|
||||||
|
private Database database;
|
||||||
|
|
||||||
|
private static final Logger log = LoggerFactory.getLogger(ServiceContainerFoundationDbDatabaseLifecycleManager.class);
|
||||||
|
|
||||||
|
ServiceContainerFoundationDbDatabaseLifecycleManager(final String foundationDbServiceContainerName) {
|
||||||
|
log.info("Using FoundationDB service container: {}", foundationDbServiceContainerName);
|
||||||
|
this.foundationDbServiceContainerName = foundationDbServiceContainerName;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void initializeDatabase(final FDB fdb) throws IOException {
|
||||||
|
final File clusterFile = File.createTempFile("fdb.cluster", "");
|
||||||
|
clusterFile.deleteOnExit();
|
||||||
|
|
||||||
|
try (final FileWriter fileWriter = new FileWriter(clusterFile)) {
|
||||||
|
fileWriter.write(String.format("docker:docker@%s:4500", foundationDbServiceContainerName));
|
||||||
|
}
|
||||||
|
|
||||||
|
// If we don't initialize the database before trying to use it, things will just hang in a mysterious, message-free
|
||||||
|
// way. Note that the `new` keyword in `configure new single memory` means that we can't accidentally clobber an
|
||||||
|
// existing database (though initialization may fail if there's already a database present).
|
||||||
|
new ProcessBuilder("/usr/bin/fdbcli",
|
||||||
|
"-C", clusterFile.getAbsolutePath(),
|
||||||
|
"--exec", "configure new single memory")
|
||||||
|
.start()
|
||||||
|
.onExit()
|
||||||
|
.join();
|
||||||
|
|
||||||
|
database = fdb.open(clusterFile.getAbsolutePath());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Database getDatabase() {
|
||||||
|
return database;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void closeDatabase() {
|
||||||
|
database.close();
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,45 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2025 Signal Messenger, LLC
|
||||||
|
* SPDX-License-Identifier: AGPL-3.0-only
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.whispersystems.textsecuregcm.storage;
|
||||||
|
|
||||||
|
import com.apple.foundationdb.Database;
|
||||||
|
import com.apple.foundationdb.FDB;
|
||||||
|
import earth.adi.testcontainers.containers.FoundationDBContainer;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
import org.testcontainers.utility.DockerImageName;
|
||||||
|
|
||||||
|
class TestcontainersFoundationDbDatabaseLifecycleManager implements FoundationDbDatabaseLifecycleManager {
|
||||||
|
|
||||||
|
private FoundationDBContainer foundationDBContainer;
|
||||||
|
private Database database;
|
||||||
|
|
||||||
|
private static final String FOUNDATIONDB_IMAGE_NAME = "foundationdb/foundationdb:" +
|
||||||
|
System.getProperty("foundationdb.version", "7.3.62");
|
||||||
|
|
||||||
|
private static final Logger log = LoggerFactory.getLogger(TestcontainersFoundationDbDatabaseLifecycleManager.class);
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void initializeDatabase(final FDB fdb) {
|
||||||
|
log.info("Using Testcontainers FoundationDB container: {}", FOUNDATIONDB_IMAGE_NAME);
|
||||||
|
|
||||||
|
foundationDBContainer = new FoundationDBContainer(DockerImageName.parse(FOUNDATIONDB_IMAGE_NAME));
|
||||||
|
foundationDBContainer.start();
|
||||||
|
|
||||||
|
database = fdb.open(foundationDBContainer.getClusterFilePath());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Database getDatabase() {
|
||||||
|
return database;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void closeDatabase() {
|
||||||
|
database.close();
|
||||||
|
foundationDBContainer.close();
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue