/* vim: set ts=2 et sw=2 cindent fo=qroca: */ package com.globant.katari.shindig; import static org.apache.shindig.config.ContainerConfig.DEFAULT_CONTAINER; import static com.globant.katari.shindig .SpringJsonContainerConfig.CONTAINER_KEY; import static com.globant.katari.shindig .SpringJsonContainerConfig.PARENT_KEY; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNull; import static org.junit.Assert.assertThat; import static org.junit.matchers.JUnitMatchers.*; import org.apache.shindig.config.ContainerConfig; import org.apache.shindig.config.ContainerConfigException; import org.apache.shindig.expressions.Expressions; import org.json.JSONObject; import org.junit.Test; import java.io.BufferedWriter; import java.io.File; import java.io.FileWriter; import java.util.ArrayList; import java.util.Arrays; import java.util.List; import java.util.Map; public class SpringJsonContainerConfigTest { private static final String TOP_LEVEL_NAME = "Top level name"; private static final String TOP_LEVEL_VALUE = "Top level value"; private static final String NESTED_KEY = "ne$ted"; private static final String NESTED_NAME = "Nested name"; private static final String NESTED_VALUE = "Nested value"; private static final String NESTED_ALT_VALUE = "Nested value alt"; private static final String CHILD_CONTAINER = "child"; private static final String CONTAINER_A = "container-a"; private static final String CONTAINER_B = "container-b"; private static final String ARRAY_NAME = "array value"; private static final String[] ARRAY_VALUE = {"Hello", "World"}; private static final String ARRAY_ALT_VALUE = "Not an array"; private File createContainer(JSONObject json) throws Exception { File file = File.createTempFile(getClass().getName(), ".json"); file.deleteOnExit(); BufferedWriter out = new BufferedWriter(new FileWriter(file)); out.write(json.toString()); out.close(); return file; } private File createDefaultContainer() throws Exception { // We use a JSON Object here to guarantee that we're well formed up front. JSONObject json = new JSONObject(); json.put(CONTAINER_KEY, new String[]{DEFAULT_CONTAINER}); json.put(TOP_LEVEL_NAME, TOP_LEVEL_VALUE); json.put(ARRAY_NAME, ARRAY_VALUE); // small nested data. JSONObject nested = new JSONObject(); nested.put(NESTED_NAME, NESTED_VALUE); json.put(NESTED_KEY, nested); return createContainer(json); } @Test public void parseBasicConfig() throws Exception { ContainerConfig config = new SpringJsonContainerConfig( createDefaultContainer().getAbsolutePath(), "localhost:8098", "/context", Expressions.forTesting()); assertEquals(1, config.getContainers().size()); for (String container : config.getContainers()) { assertEquals(DEFAULT_CONTAINER, container); } String value = config.getString(DEFAULT_CONTAINER, TOP_LEVEL_NAME); assertEquals(TOP_LEVEL_VALUE, value); Map<String, Object> nested = config.getMap(DEFAULT_CONTAINER, NESTED_KEY); String nestedValue = nested.get(NESTED_NAME).toString(); assertEquals(NESTED_VALUE, nestedValue); } @Test public void aliasesArePopulated() throws Exception { JSONObject json = new JSONObject() .put(CONTAINER_KEY, new String[]{CONTAINER_A, CONTAINER_B}) .put(NESTED_KEY, NESTED_VALUE); File parentFile = createDefaultContainer(); File childFile = createContainer(json); ContainerConfig config = new SpringJsonContainerConfig( childFile.getAbsolutePath() + SpringJsonContainerConfig.FILE_SEPARATOR + parentFile.getAbsolutePath(), "localhost:8098", "/context", Expressions.forTesting()); assertEquals(NESTED_VALUE, config.getString(CONTAINER_A, NESTED_KEY)); assertEquals(NESTED_VALUE, config.getString(CONTAINER_B, NESTED_KEY)); } @Test public void parseWithDefaultInheritance() throws Exception { JSONObject json = new JSONObject(); json.put(CONTAINER_KEY, new String[]{CHILD_CONTAINER}); json.put(PARENT_KEY, DEFAULT_CONTAINER); json.put(ARRAY_NAME, ARRAY_ALT_VALUE); // small nested data. JSONObject nested = new JSONObject(); nested.put(NESTED_NAME, NESTED_ALT_VALUE); json.put(NESTED_KEY, nested); File childFile = createContainer(json); File parentFile = createDefaultContainer(); ContainerConfig config = new SpringJsonContainerConfig( childFile.getAbsolutePath() + SpringJsonContainerConfig.FILE_SEPARATOR + parentFile.getAbsolutePath(), "localhost:8098", "/context", Expressions.forTesting()); String value = config.getString(CHILD_CONTAINER, TOP_LEVEL_NAME); assertEquals(TOP_LEVEL_VALUE, value); Map<String, Object> nestedObj = config.getMap(CHILD_CONTAINER, NESTED_KEY); String nestedValue = nestedObj.get(NESTED_NAME).toString(); assertEquals(NESTED_ALT_VALUE, nestedValue); String arrayValue = config.getString(CHILD_CONTAINER, ARRAY_NAME); assertEquals(ARRAY_ALT_VALUE, arrayValue); // Verify that the parent value wasn't overwritten as well. List<String> actual = new ArrayList<String>(); for (Object val : config.getList(DEFAULT_CONTAINER, ARRAY_NAME)) { actual.add(val.toString()); } List<String> expected = Arrays.asList(ARRAY_VALUE); assertEquals(expected, actual); } @Test public void invalidContainerReturnsNull() throws Exception { ContainerConfig config = new SpringJsonContainerConfig( createDefaultContainer().getAbsolutePath(), "localhost:8098", "/config", Expressions.forTesting()); assertNull("Did not return null for invalid container.", config.getString("fake", PARENT_KEY)); } @Test(expected = ContainerConfigException.class) public void badConfigThrows() throws Exception { JSONObject json = new JSONObject(); json.put(CONTAINER_KEY, new String[]{CHILD_CONTAINER}); json.put(PARENT_KEY, "bad bad bad parent!"); json.put(ARRAY_NAME, ARRAY_ALT_VALUE); new SpringJsonContainerConfig(createContainer(json).getAbsolutePath(), "localhost:8098", "/context", Expressions.forTesting()); } @Test public void pathQuery() throws Exception { ContainerConfig config = new SpringJsonContainerConfig( createDefaultContainer().getAbsolutePath(), "localhost:8098", "/context", Expressions.forTesting()); String path = "${" + NESTED_KEY + "['" + NESTED_NAME + "']}"; String data = config.getString(DEFAULT_CONTAINER, path); assertEquals(NESTED_VALUE, data); } @Test public void expressionEvaluation() throws Exception { // We use a JSON Object here to guarantee that we're well formed up front. JSONObject json = new JSONObject(); json.put(CONTAINER_KEY, new String[]{DEFAULT_CONTAINER}); json.put("expression", "Hello, ${world}!"); json.put("world", "Earth"); ContainerConfig config = new SpringJsonContainerConfig( createContainer(json).getAbsolutePath(), "localhost:8098", "/context", Expressions.forTesting()); assertEquals("Hello, Earth!", config.getString(DEFAULT_CONTAINER, "expression")); } @Test public void expressionEvaluationUsingParent() throws Exception { // We use a JSON Object here to guarantee that we're well formed up front. JSONObject json = new JSONObject(); json.put(CONTAINER_KEY, new String[]{CHILD_CONTAINER}); json.put(PARENT_KEY, DEFAULT_CONTAINER); json.put("parentExpression", "${parent['" + TOP_LEVEL_NAME + "']}"); File childFile = createContainer(json); File parentFile = createDefaultContainer(); ContainerConfig config = new SpringJsonContainerConfig( childFile.getAbsolutePath() + SpringJsonContainerConfig.FILE_SEPARATOR + parentFile.getAbsolutePath(), "localhost:8098", "/context", Expressions.forTesting()); assertEquals(TOP_LEVEL_VALUE, config.getString(CHILD_CONTAINER, "parentExpression")); } @Test public void nullEntryEvaluation() throws Exception { // We use a JSON Object here to guarantee that we're well formed up front. JSONObject json = new JSONObject( "{ 'gadgets.container' : ['default'], features : { osapi : null }}"); SpringJsonContainerConfig config = new SpringJsonContainerConfig( createContainer(json).getAbsolutePath(), "localhost:8098", "/context", Expressions.forTesting()); assertNull(config.getMap("default", "features").get("osapi")); } /* Test related to %context% replacement. */ /* Creates a container with a %context% val. */ private String createContextContainer() throws Exception { // We use a JSON Object here to guarantee that we're well formed up front. JSONObject json = new JSONObject(); json.put(CONTAINER_KEY, new String[]{DEFAULT_CONTAINER}); json.put(TOP_LEVEL_NAME, TOP_LEVEL_VALUE); json.put(ARRAY_NAME, ARRAY_VALUE); // small nested data. JSONObject nestedJson = new JSONObject(); nestedJson.put(NESTED_NAME, "%context%/" + NESTED_VALUE); nestedJson.put("endpoint", "%hostAndPort%/" + NESTED_VALUE); json.put(NESTED_KEY, nestedJson); File childFile = createContainer(json); return childFile.getAbsolutePath(); } @Test public void constructor_context() throws Exception { ContainerConfig config = new SpringJsonContainerConfig( createContextContainer(), "localhost:8098", "/context", Expressions.forTesting()); Map<String, Object> nested = config.getMap(DEFAULT_CONTAINER, NESTED_KEY); String nestedValue = nested.get(NESTED_NAME).toString(); assertThat(nestedValue, containsString("/context/")); } @Test public void constructor_contextNoSlash() throws Exception { ContainerConfig config = new SpringJsonContainerConfig( createContextContainer(), "localhost:8098", "context", Expressions.forTesting()); Map<String, Object> nested = config.getMap(DEFAULT_CONTAINER, NESTED_KEY); String nestedValue = nested.get(NESTED_NAME).toString(); assertThat(nestedValue, containsString("/context/")); } @Test public void constructor_contextOnlyTrailing() throws Exception { ContainerConfig config = new SpringJsonContainerConfig( createContextContainer(), "localhost:8098", "context/", Expressions.forTesting()); Map<String, Object> nested = config.getMap(DEFAULT_CONTAINER, NESTED_KEY); String nestedValue = nested.get(NESTED_NAME).toString(); assertThat(nestedValue, containsString("/context/")); } @Test public void constructor_contextTwoSlashes() throws Exception { ContainerConfig config = new SpringJsonContainerConfig( createContextContainer(), "localhost:8098", "context/", Expressions.forTesting()); Map<String, Object> nested = config.getMap(DEFAULT_CONTAINER, NESTED_KEY); String nestedValue = nested.get(NESTED_NAME).toString(); assertThat(nestedValue, containsString("/context/")); nestedValue = nested.get("endpoint").toString(); assertThat(nestedValue, containsString("localhost:8098")); } }