From 602d392e17dffacb4e98792275a94a0f09226f3e Mon Sep 17 00:00:00 2001 From: Wyatt Walter Date: Wed, 23 Sep 2026 08:59:40 -0500 Subject: [PATCH] test(server): run embedded MongoDB natively on Apple Silicon --- app/server/appsmith-server/pom.xml | 7 +- .../EmbeddedMongoPackageTest.java | 71 ++++++++++++++ .../configurations/EmbeddedMongoTest.java | 98 +++++++++++++++++++ .../resources/application-test.properties | 4 +- contributions/ServerSetup.md | 17 ++++ 5 files changed, 192 insertions(+), 5 deletions(-) create mode 100644 app/server/appsmith-server/src/test/java/com/appsmith/server/configurations/EmbeddedMongoPackageTest.java create mode 100644 app/server/appsmith-server/src/test/java/com/appsmith/server/configurations/EmbeddedMongoTest.java diff --git a/app/server/appsmith-server/pom.xml b/app/server/appsmith-server/pom.xml index e8dde563432f..5b55099f6730 100644 --- a/app/server/appsmith-server/pom.xml +++ b/app/server/appsmith-server/pom.xml @@ -16,6 +16,7 @@ This is the API server for the Appsmith project + 4.33.0 1.35 2.4.4 @@ -173,13 +174,13 @@ de.flapdoodle.embed de.flapdoodle.embed.mongo - 4.12.0 + ${flapdoodle.version} test de.flapdoodle.embed - de.flapdoodle.embed.mongo.spring30x - 4.11.0 + de.flapdoodle.embed.mongo.spring3x + ${flapdoodle.version} test diff --git a/app/server/appsmith-server/src/test/java/com/appsmith/server/configurations/EmbeddedMongoPackageTest.java b/app/server/appsmith-server/src/test/java/com/appsmith/server/configurations/EmbeddedMongoPackageTest.java new file mode 100644 index 000000000000..0a7905283893 --- /dev/null +++ b/app/server/appsmith-server/src/test/java/com/appsmith/server/configurations/EmbeddedMongoPackageTest.java @@ -0,0 +1,71 @@ +package com.appsmith.server.configurations; + +import de.flapdoodle.embed.mongo.packageresolver.Command; +import de.flapdoodle.embed.mongo.packageresolver.PlatformPackageResolver; +import de.flapdoodle.embed.process.distribution.Distribution; +import de.flapdoodle.embed.process.distribution.Version; +import de.flapdoodle.os.CommonArchitecture; +import de.flapdoodle.os.CommonOS; +import de.flapdoodle.os.ImmutablePlatform; +import de.flapdoodle.os.Platform; +import de.flapdoodle.os.linux.LinuxDistribution; +import de.flapdoodle.os.linux.UbuntuVersion; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.Arguments; +import org.junit.jupiter.params.provider.MethodSource; +import org.springframework.core.io.ClassPathResource; +import org.springframework.core.io.support.PropertiesLoaderUtils; + +import java.io.IOException; +import java.util.stream.Stream; + +import static org.assertj.core.api.Assertions.assertThat; + +class EmbeddedMongoPackageTest { + + @ParameterizedTest + @MethodSource("platforms") + void configuredVersion_resolvesNativePackage(Platform platform, String archivePrefix) throws IOException { + String version = PropertiesLoaderUtils.loadProperties(new ClassPathResource("application-test.properties")) + .getProperty("de.flapdoodle.mongodb.embedded.version"); + + String url = new PlatformPackageResolver(Command.MongoD) + .packageFor(Distribution.of(Version.of(version), platform)) + .url(); + + assertThat(url).startsWith(archivePrefix + version + "."); + } + + private static Stream platforms() { + return Stream.of( + Arguments.of( + ImmutablePlatform.builder() + .operatingSystem(CommonOS.OS_X) + .architecture(CommonArchitecture.ARM_64) + .build(), + "/osx/mongodb-macos-arm64-"), + Arguments.of( + ImmutablePlatform.builder() + .operatingSystem(CommonOS.OS_X) + .architecture(CommonArchitecture.X86_64) + .build(), + "/osx/mongodb-macos-x86_64-"), + Arguments.of(ubuntu(CommonArchitecture.X86_64), "/linux/mongodb-linux-x86_64-ubuntu2204-"), + Arguments.of(ubuntu(CommonArchitecture.ARM_64), "/linux/mongodb-linux-aarch64-ubuntu2204-"), + Arguments.of( + ImmutablePlatform.builder() + .operatingSystem(CommonOS.Windows) + .architecture(CommonArchitecture.X86_64) + .build(), + "/windows/mongodb-windows-x86_64-")); + } + + private static Platform ubuntu(CommonArchitecture architecture) { + return ImmutablePlatform.builder() + .operatingSystem(CommonOS.Linux) + .architecture(architecture) + .distribution(LinuxDistribution.Ubuntu) + .version(UbuntuVersion.Ubuntu_22_04) + .build(); + } +} diff --git a/app/server/appsmith-server/src/test/java/com/appsmith/server/configurations/EmbeddedMongoTest.java b/app/server/appsmith-server/src/test/java/com/appsmith/server/configurations/EmbeddedMongoTest.java new file mode 100644 index 000000000000..fff5235e33f2 --- /dev/null +++ b/app/server/appsmith-server/src/test/java/com/appsmith/server/configurations/EmbeddedMongoTest.java @@ -0,0 +1,98 @@ +package com.appsmith.server.configurations; + +import com.mongodb.reactivestreams.client.ClientSession; +import com.mongodb.reactivestreams.client.MongoClient; +import com.mongodb.reactivestreams.client.MongoCollection; +import de.flapdoodle.embed.mongo.spring.autoconfigure.EmbeddedMongoAutoConfiguration; +import org.bson.Document; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.boot.autoconfigure.ImportAutoConfiguration; +import org.springframework.boot.autoconfigure.mongo.MongoAutoConfiguration; +import org.springframework.boot.autoconfigure.mongo.MongoReactiveAutoConfiguration; +import org.springframework.boot.test.context.TestConfiguration; +import org.springframework.context.annotation.Import; +import org.springframework.test.context.TestPropertySource; +import org.springframework.test.context.junit.jupiter.SpringJUnitConfig; +import reactor.core.publisher.Mono; + +import java.time.Duration; +import java.util.Locale; + +import static org.assertj.core.api.Assertions.assertThat; + +@SpringJUnitConfig(EmbeddedMongoTest.MongoTestConfig.class) +@TestPropertySource(locations = "classpath:application-test.properties") +class EmbeddedMongoTest { + + private static final Duration TIMEOUT = Duration.ofSeconds(15); + + @Autowired + private MongoClient mongoClient; + + @Value("${de.flapdoodle.mongodb.embedded.version}") + private String configuredVersion; + + @Test + void configuredVersion_runsNativelyWithReplicaSet() { + Document buildInfo = Mono.from(mongoClient.getDatabase("admin").runCommand(new Document("buildInfo", 1))) + .block(TIMEOUT); + assertThat(buildInfo).isNotNull(); + assertThat(buildInfo.getString("version")).isEqualTo(configuredVersion); + + String architecture = System.getProperty("os.arch").toLowerCase(Locale.ROOT); + String mongoArchitecture = + buildInfo.get("buildEnvironment", Document.class).getString("target_arch"); + if (architecture.equals("aarch64") || architecture.equals("arm64")) { + assertThat(mongoArchitecture).isIn("aarch64", "arm64"); + } else if (architecture.equals("amd64") || architecture.equals("x86_64")) { + assertThat(mongoArchitecture).isIn("x86_64", "amd64"); + } else { + assertThat(mongoArchitecture).isEqualTo(architecture); + } + + Document hello = Mono.from(mongoClient.getDatabase("admin").runCommand(new Document("hello", 1))) + .block(TIMEOUT); + assertThat(hello).containsEntry("setName", "appsmith-replica-set").containsEntry("isWritablePrimary", true); + } + + @Test + void replicaSet_supportsTransactionCommitAndAbort() { + MongoCollection collection = + mongoClient.getDatabase("embedded_mongo_smoke").getCollection("transactions"); + Mono.from(collection.insertOne(new Document("_id", "existing"))).block(TIMEOUT); + try (ClientSession session = Mono.from(mongoClient.startSession()).block(TIMEOUT)) { + assertThat(session).isNotNull(); + assertThat(Mono.from(collection.countDocuments()).block(TIMEOUT)).isEqualTo(1); + + session.startTransaction(); + Mono.from(collection.insertOne(session, new Document("_id", "committed"))) + .block(TIMEOUT); + Mono.from(session.commitTransaction()).block(TIMEOUT); + assertThat(Mono.from(collection.countDocuments()).block(TIMEOUT)).isEqualTo(2); + + session.startTransaction(); + Mono.from(collection.insertOne(session, new Document("_id", "aborted"))) + .block(TIMEOUT); + assertThat(Mono.from(collection.countDocuments(session)).block(TIMEOUT)) + .isEqualTo(3); + Mono.from(session.abortTransaction()).block(TIMEOUT); + assertThat(Mono.from(collection.countDocuments()).block(TIMEOUT)).isEqualTo(2); + assertThat(Mono.from(collection.find(new Document("_id", "aborted")).first()) + .block(TIMEOUT)) + .isNull(); + } finally { + Mono.from(collection.drop()).block(TIMEOUT); + } + } + + @TestConfiguration(proxyBeanMethods = false) + @Import(TransactionalConfig.class) + @ImportAutoConfiguration({ + EmbeddedMongoAutoConfiguration.class, + MongoAutoConfiguration.class, + MongoReactiveAutoConfiguration.class + }) + static class MongoTestConfig {} +} diff --git a/app/server/appsmith-server/src/test/resources/application-test.properties b/app/server/appsmith-server/src/test/resources/application-test.properties index 324efe64371f..c674b235c076 100644 --- a/app/server/appsmith-server/src/test/resources/application-test.properties +++ b/app/server/appsmith-server/src/test/resources/application-test.properties @@ -1,5 +1,5 @@ -# embedded mongo DB version which is used during junit tests -de.flapdoodle.mongodb.embedded.version=5.0.5 +# Embedded MongoDB for JUnit tests; Flapdoodle selects the native OS/CPU build. +de.flapdoodle.mongodb.embedded.version=7.0.34 logging.level.root=error appsmith.git.root = /dev/shm/git-storage diff --git a/contributions/ServerSetup.md b/contributions/ServerSetup.md index 54dcdcd7c9ae..7966c5a1a70d 100644 --- a/contributions/ServerSetup.md +++ b/contributions/ServerSetup.md @@ -437,6 +437,23 @@ mvn -B clean compile && ./build.sh -DskipTests ``` ## Running Tests on Server +MongoDB-backed JUnit tests use an isolated replica set started by Flapdoodle. The +MongoDB version is pinned in +`app/server/appsmith-server/src/test/resources/application-test.properties`. +Flapdoodle downloads the build for the operating system and CPU architecture and +caches it under `~/.embedmongo`. A separately installed MongoDB is not required for +these tests. On Apple Silicon, use an ARM64 JDK; `mvn -v` should report `aarch64` or +`arm64` as the architecture. + +To check native MongoDB startup, platform package selection, and transaction +commit/rollback without starting Redis, run from `app/server`: + +```bash +mvn -pl appsmith-server -am test \ + -Dtest=EmbeddedMongoPackageTest,EmbeddedMongoTest \ + -Dsurefire.failIfNoSpecifiedTests=false +``` + 1. Ensure that you have Redis running on your local system. 2. Run the command to execute tests from repo root: