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>
|
||||
<scope>import</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>earth.adi</groupId>
|
||||
<artifactId>testcontainers-foundationdb</artifactId>
|
||||
<version>1.1.0</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</dependencyManagement>
|
||||
|
||||
|
|
|
@ -502,6 +502,12 @@
|
|||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>earth.adi</groupId>
|
||||
<artifactId>testcontainers-foundationdb</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>com.google.auth</groupId>
|
||||
<artifactId>google-auth-library-oauth2-http</artifactId>
|
||||
|
@ -733,6 +739,7 @@
|
|||
<!-- 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>
|
||||
<systemPropertyVariables>
|
||||
<foundationdb.version>${foundationdb.version}</foundationdb.version>
|
||||
<localstackImage>${localstack.image}</localstackImage>
|
||||
</systemPropertyVariables>
|
||||
</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