Skip to content
Open
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

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -35,10 +35,10 @@ public abstract class AbstractFeatureTest {

@BeforeClass
public static void setUp() throws Exception {
final InputStream stream = GremlinServer.class.getResourceAsStream("gremlin-server-integration.yaml");
final Settings settings = Settings.read(stream);
ServerTestHelper.rewritePathsInGremlinServerSettings(settings);
var filePath = "classpath:" + GremlinServer.class.getPackageName().replace(".", "/") + "/gremlin-server-integration.yaml";
final Settings settings = Settings.read(filePath);

ServerTestHelper.rewritePathsInGremlinServerSettings(settings);
server = new GremlinServer(settings);
server.start().get(100, TimeUnit.SECONDS);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -209,8 +209,8 @@ public static Cluster.Builder createClusterBuilder(final Serializers serializer)
}

public static void startServer() throws Exception {
final InputStream stream = GremlinServer.class.getResourceAsStream("gremlin-server-integration.yaml");
final Settings settings = Settings.read(stream);
var filePath = "classpath:" + GremlinServer.class.getPackageName().replace(".", "/") + "/gremlin-server-integration.yaml";
final Settings settings = Settings.read(filePath);
ServerTestHelper.rewritePathsInGremlinServerSettings(settings);

settings.maxContentLength = 1024000;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -82,9 +82,6 @@ protected void overrideEvaluationTimeout(final long timeoutInMillis) {
overriddenSettings.evaluationTimeout = timeoutInMillis;
}

public InputStream getSettingsInputStream() {
return AbstractGremlinServerIntegrationTest.class.getResourceAsStream("gremlin-server-integration.yaml");
}

@Before
public void setUp() throws Exception {
Expand Down Expand Up @@ -123,8 +120,8 @@ public void startServer() throws Exception {
}

public CompletableFuture<ServerGremlinExecutor> startServerAsync() throws Exception {
final InputStream stream = getSettingsInputStream();
final Settings settings = Settings.read(stream);
var filePath = "classpath:" + GremlinServer.class.getPackageName().replace(".", "/") + "/gremlin-server-integration.yaml";
final Settings settings = Settings.read(filePath);
overriddenSettings = overrideSettings(settings);
ServerTestHelper.rewritePathsInGremlinServerSettings(overriddenSettings);
if (GREMLIN_SERVER_EPOLL) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -51,8 +51,8 @@ public InputStream getSettingsInputStream() {
}

public Settings getBaseSettings() {
final InputStream stream = getSettingsInputStream();
return Settings.read(stream);
var filePath = "classpath:" + GremlinServer.class.getPackageName().replace(".", "/") + "/gremlin-server-integration.yaml";
return Settings.read(filePath);
}

public CompletableFuture<ServerGremlinExecutor> startServer(final Settings settings) throws Exception {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,15 +18,33 @@
*/
package org.apache.tinkerpop.gremlin.server;

import org.junit.Test;
import org.apache.commons.io.FileUtils;
import org.junit.*;
import org.yaml.snakeyaml.Yaml;
import org.yaml.snakeyaml.constructor.Constructor;

import java.io.IOException;
import java.io.InputStream;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.List;
import java.util.Map;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.*;

public class SettingsTest {
private Path tempDir;

@Before
public void before() throws Exception {
tempDir = Files.createTempDirectory(SettingsTest.class.getSimpleName());
}

@After
public void afterClass() throws Exception {
FileUtils.deleteDirectory(tempDir.toFile());
}

private static class CustomSettings extends Settings {
public String customValue = "localhost";
Expand All @@ -39,7 +57,7 @@ public static CustomSettings read(final InputStream stream) {
}

@Test
public void constructorCanBeExtendToParseCustomYamlAndSettingsValues() throws Exception {
public void constructorCanBeExtendToParseCustomYamlAndSettingsValues() {
final InputStream stream = SettingsTest.class.getResourceAsStream("custom-gremlin-server.yaml");

final CustomSettings settings = CustomSettings.read(stream);
Expand All @@ -49,11 +67,228 @@ public void constructorCanBeExtendToParseCustomYamlAndSettingsValues() throws Ex
}

@Test
public void defaultCustomValuesAreHandledCorrectly() throws Exception {
public void defaultCustomValuesAreHandledCorrectly() {
final InputStream stream = SettingsTest.class.getResourceAsStream("gremlin-server-integration.yaml");

final CustomSettings settings = CustomSettings.read(stream);

assertEquals("localhost", settings.customValue);
}

@Test
public void testSimpleIncludeAndMerge() throws IOException {
createFile("base.yaml", "graphs: { graph1: 'base1', graph2: 'base2' }");
createFile("root.yaml",
"includes: ['base.yaml']\n" +
"graphs:\n" +
" graph1: 'root'"

);

Settings result = Settings.read(tempDir.resolve("root.yaml").toString());

assertEquals("root", result.graphs.get("graph1"));
assertEquals("base2", result.graphs.get("graph2"));
}

@Test
public void testDeepMerge() throws IOException {
createFile("base.yaml",
"scriptEngines:\n" +
" engine1:\n" +
" config: \n" +
" connector: { port: 8080, protocol: 'http' }\n" +
" logging: { level: 'INFO' }"
);
createFile("root.yaml",
"includes: ['base.yaml']\n" +
"scriptEngines:\n" +
" engine1:\n" +
" config: \n" +
" connector: { port: 9090 }\n" +
" logging: { file: '/var/log/app.log' }"
);


Settings result = Settings.read(tempDir.resolve("root.yaml").toString());
@SuppressWarnings("unchecked")
Map<String, Object> connector = (Map<String, Object>) result.scriptEngines.get("engine1").config.get("connector");
@SuppressWarnings("unchecked")
Map<String, Object> logging = (Map<String, Object>) result.scriptEngines.get("engine1").config.get("logging");

assertEquals(9090, connector.get("port"));
assertEquals("http", connector.get("protocol"));
assertEquals("INFO", logging.get("level"));
assertEquals("/var/log/app.log", logging.get("file"));
}

@Test
public void testMultipleIncludesOrder() throws IOException {
// Arrange
createFile("one.yaml", "host: localhost1");
createFile("two.yaml", "host: localhost2");
createFile("root.yaml",
"includes: ['one.yaml', 'two.yaml']\n" // two should overwrite one
);

Settings result = Settings.read(tempDir.resolve("root.yaml").toString());

assertEquals("localhost2", result.host);
}

@Test
public void testListReplacement() throws IOException {
createFile("base.yaml", "serializers: \n" +
" [ {className: 'a'} , {className: 'b' }]");
createFile("root.yaml",
"includes: ['base.yaml']\n" +
"serializers: \n" +
" [ {className: 'c'}]");
Settings result = Settings.read(tempDir.resolve("root.yaml").toString());

List<Settings.SerializerSettings> serializers = result.serializers;
assertEquals(1, serializers.size());
assertEquals("c", serializers.get(0).className);
}

@Test
public void testRelativePathResolution() throws IOException {
// Structure:
// root.yaml
// subdir/
// child.yaml
// nested/
// grandchild.yaml

createFile("subdir/nested/grandchild.yaml", "host: 0.0.0.0");
createFile("subdir/child.yaml",
"includes: ['nested/grandchild.yaml']\n" +
"port: 9090"
);
createFile("root.yaml",
"includes: ['subdir/child.yaml']\n" +
"threadPoolWorker: 1000"
);

Settings result = Settings.read(tempDir.resolve("root.yaml").toString());
assertEquals(9090, result.port);
assertEquals(1000, result.threadPoolWorker);
assertEquals("0.0.0.0", result.host);
}

@Test
public void testParentPathResolution() throws IOException {
// root.yaml -> includes 'config/sub.yaml'
// config/sub.yaml -> includes '../shared.yaml'

createFile("shared.yaml", "host: 0.0.0.0");
createFile("config/sub.yaml", "includes: ['../shared.yaml']");
createFile("root.yaml", "includes: ['config/sub.yaml']");

Settings result = Settings.read(tempDir.resolve("root.yaml").toString());

assertEquals("0.0.0.0", result.host);
}

@Test
public void testCircularDependency() throws IOException {
createFile("a.yaml", "includes: ['b.yaml']");
createFile("b.yaml", "includes: ['a.yaml']");

try {
Settings.read(tempDir.resolve("a.yaml").toString());
Assert.fail("Expected exception");
} catch (Exception e) {
assertTrue(e.getMessage().contains("Circular dependency detected"));
}
}

@Test
public void testDiamondDependency() throws IOException {
// A -> B, A -> C
// B -> D
// C -> D
// This is valid. D should be loaded twice (or handled gracefully) but not cause a cycle error.

createFile("d.yaml", "host: '0.0.0.0'");
createFile("b.yaml", "includes: ['d.yaml']\nport: 9090");
createFile("c.yaml", "includes: ['d.yaml']\nthreadPoolWorker: 1000");
createFile("a.yaml", "includes: ['b.yaml', 'c.yaml']");

Settings result = Settings.read(tempDir.resolve("a.yaml").toString());
assertEquals(9090, result.port);
assertEquals(1000, result.threadPoolWorker);
assertEquals("0.0.0.0", result.host);
}

@Test
public void testClasspathResolution() {
Settings result = Settings.read("classpath:org/apache/tinkerpop/gremlin/server/settings/config/root.yaml");

assertEquals(9090, result.port);
assertEquals(1000, result.threadPoolWorker);
assertEquals("localhost1", result.host);
}

@Test
public void testFileSystemIncludingClasspath() throws IOException {
createFile("disk.yaml", "includes: ['classpath:org/apache/tinkerpop/gremlin/server/settings/config/root.yaml']\ngremlinPool: 2000");
Settings result = Settings.read(tempDir.resolve("disk.yaml").toString());

assertEquals(9090, result.port);
assertEquals(1000, result.threadPoolWorker);
assertEquals("localhost1", result.host);
assertEquals(2000, result.gremlinPool);
}

@Test
public void testMissingFile() {
try {
Settings.read(tempDir.resolve("root.yaml").toString());
Assert.fail("Expected exception");
} catch (Exception e) {
String msg = e.getMessage();
assertTrue(msg.contains("root.yaml"));
assertTrue(msg.contains("Error loading YAML from"));
}
}

@Test
public void testMissingIncludedFile() throws IOException {
createFile("root.yaml", "includes: ['non_existent.yaml']");
try {
Settings.read(tempDir.resolve("root.yaml").toString());
Assert.fail("Expected exception");
} catch (Exception e) {
String msg = e.getMessage();
assertTrue(msg.contains("non_existent.yaml"));
assertTrue(msg.contains("Error loading YAML from"));
}
}

@Test
public void testMalformedIncludes() throws IOException {
createFile("root.yaml", "includes: 'just_a_string.yaml'");

try {
Settings.read(tempDir.resolve("root.yaml").toString());
Assert.fail("Expected exception");
} catch (Exception e) {
String msg = e.getMessage();
assertTrue(msg.contains("'includes' must be a list of strings"));
}
}

@Test
public void testEmptyFile() throws IOException {
createFile("empty.yaml", "");
Settings settings = Settings.read(tempDir.resolve("empty.yaml").toString());
assertNotNull(settings);
}

private void createFile(String fileName, String content) throws IOException {
Path file = tempDir.resolve(fileName);
Files.createDirectories(file.getParent());
Files.write(file, content.getBytes(StandardCharsets.UTF_8));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
import java.util.function.Function;

import org.apache.tinkerpop.gremlin.server.GraphManager;
import org.apache.tinkerpop.gremlin.server.GremlinServer;
import org.apache.tinkerpop.gremlin.server.Settings;

import org.junit.Before;
Expand All @@ -36,8 +37,8 @@ public class CheckedGraphManagerTest {

@Before
public void before() throws Exception {
settings = Settings
.read(CheckedGraphManagerTest.class.getResourceAsStream("../gremlin-server-integration.yaml"));
var filePath = "classpath:" + GremlinServer.class.getPackageName().replace(".", "/") + "/gremlin-server-integration.yaml";
settings = Settings.read(filePath);
}

/**
Expand Down
Loading
Loading