/* * Copyright 2013 eBuddy B.V. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.ebuddy.cassandra.structure; import static org.testng.Assert.assertEquals; import java.util.Arrays; import java.util.Collections; import java.util.HashMap; import java.util.Map; import org.testng.annotations.BeforeMethod; import org.testng.annotations.Test; import com.ebuddy.cassandra.Path; import com.google.common.collect.ImmutableMap; /** * Tests for Composer. * * @author Eric Zoerner <a href="mailto:ezoerner@ebuddy.com">ezoerner@ebuddy.com</a> */ @SuppressWarnings({"MagicNumber", "CloneableClassWithoutClone"}) public class ComposerTest { private Composer composer; @BeforeMethod(alwaysRun = true) public void setUp() throws Exception { composer = Composer.get(); } @Test(groups = "unit", expectedExceptions = IllegalArgumentException.class) public void composeNull() throws Exception { composer.compose(null); } @Test(groups = "unit") public void composeEmpty() throws Exception { Object result = composer.compose(new HashMap<Path,Object>()); assertEquals(result, Collections.emptyMap()); } @Test(groups = "unit") public void composeSimpleObjectsWithSimplePaths() throws Exception { Map<Path,Object> simpleObjects = new HashMap<Path,Object>(); simpleObjects.put(DefaultPath.fromStrings("x"), ""); simpleObjects.put(DefaultPath.fromStrings("y"), 42); simpleObjects.put(DefaultPath.fromStrings("z"), true); simpleObjects.put(DefaultPath.fromStrings("N"), null); ///////////// Object result = composer.compose(simpleObjects); ///////////// // output of only simple objects is equal to the input, but has strings as keys instead of Paths Map<String,Object> expectedResult = new HashMap<String,Object>(); for (Map.Entry<Path,Object> entry : simpleObjects.entrySet()) { expectedResult.put(entry.getKey().head(), entry.getValue()); } assertEquals(result, expectedResult); } @Test(groups = "unit") public void composeSimpleObjectsWithLongerPaths() throws Exception { Map<Path,Object> simpleObjects = new HashMap<Path,Object>(); simpleObjects.put(DefaultPath.fromEncodedPathString("a%2F%40%23/b/c"), ""); simpleObjects.put(DefaultPath.fromEncodedPathString("a%2F%40%23/b/d"), 42); simpleObjects.put(DefaultPath.fromEncodedPathString("d/e/f"), true); simpleObjects.put(DefaultPath.fromEncodedPathString("d/f/g"), false); simpleObjects.put(DefaultPath.fromEncodedPathString("j/k/l"), null); ///////////// Object result = composer.compose(simpleObjects); ///////////// Map<String,Object> expectedResult = getExpectedMapForComposeSimpleObjectWithLongerPaths(); assertEquals(result, expectedResult); } @Test(groups = {"unit"}) public void composeList() throws Exception { Map<Path,Object> simpleObjects = new HashMap<Path,Object>(); simpleObjects.put(DefaultPath.fromEncodedPathString("a/@0"), ""); simpleObjects.put(DefaultPath.fromEncodedPathString("a/@1"), 42); ///////////// Object result = composer.compose(simpleObjects); ///////////// Map<String,Object> expectedResult = new HashMap<String,Object>(); expectedResult.put("a", Arrays.asList("", 42)); assertEquals(result, expectedResult); } @Test(groups = {"unit"}) public void composeListWithDeletedIndex() throws Exception { Map<Path,Object> simpleObjects = new HashMap<Path,Object>(); simpleObjects.put(DefaultPath.fromEncodedPathString("a/@0"), ""); simpleObjects.put(DefaultPath.fromEncodedPathString("a/@2"), 42); ///////////// Object result = composer.compose(simpleObjects); ///////////// Map<String,Object> expectedResult = new HashMap<String,Object>(); expectedResult.put("a", Arrays.asList("", 42)); assertEquals(result, expectedResult); } @Test(groups = {"unit"}) public void composeListOfMaps() throws Exception { Map<Path,Object> simpleObjects = new HashMap<Path,Object>(); simpleObjects.put(DefaultPath.fromEncodedPathString("a/@0/b"), ""); simpleObjects.put(DefaultPath.fromEncodedPathString("a/@0/c"), 42); simpleObjects.put(DefaultPath.fromEncodedPathString("a/@1/b"), ""); simpleObjects.put(DefaultPath.fromEncodedPathString("a/@1/c"), 42); ///////////// Object result = composer.compose(simpleObjects); ///////////// Map<String,Object> expectedResult = new HashMap<String,Object>(); Map<String,Object> innerMap = new HashMap<String,Object>() {{ put("b", ""); put("c", 42); }}; expectedResult.put("a", Arrays.asList(innerMap, innerMap)); assertEquals(result, expectedResult); } @Test(groups = {"unit"}) public void composeMapOfLists() throws Exception { Map<Path,Object> simpleObjects = new HashMap<Path,Object>(); simpleObjects.put(DefaultPath.fromEncodedPathString("a/@0"), ""); simpleObjects.put(DefaultPath.fromEncodedPathString("a/@1"), 42); simpleObjects.put(DefaultPath.fromEncodedPathString("b/@0"), ""); simpleObjects.put(DefaultPath.fromEncodedPathString("b/@1"), 42); ///////////// Object result = composer.compose(simpleObjects); ///////////// Map<String,Object> expectedResult = new HashMap<String,Object>() {{ put("a", Arrays.asList("",42)); put("b", Arrays.asList("",42)); }}; assertEquals(result, expectedResult); } @Test(groups = {"unit"}, description = "tests the inconsistent root when the structure comes first in iteration order") public void shouldComposeInconsistentRoot() throws Exception { Map<Path,Object> map = ImmutableMap.<Path,Object>of(DefaultPath.fromEncodedPathString("a/b/"), "c", DefaultPath.fromEncodedPathString("a/"), "d"); // inconsistent paths, cannot have both a map (with key b) at "a/" and also a simple object at "a/" ///////////// Object result = composer.compose(map); ///////////// // expected result has no loss of information with special key used for the inconsistent root Map<String,Object> expectedResult = ImmutableMap.<String,Object>of("a", ImmutableMap.of("b", "c", "@ROOT", "d")); assertEquals(result, expectedResult); } @Test(groups = {"unit"}, description = "tests the inconsistent root when the simple value comes first in iteration order") public void shouldComposeInconsistentRootOtherOrder() throws Exception { // guava ImmutableMaps have user-defined iteration order :-) Map<Path,Object> map = ImmutableMap.<Path,Object>of(DefaultPath.fromEncodedPathString("a/"), "d", DefaultPath.fromEncodedPathString("a/b/"), "c"); // inconsistent paths, cannot have both a map (with key b) at "a/" and also a simple object at "a/" ///////////// Object result = composer.compose(map); ///////////// // expected result has no loss of information with special key used for the inconsistent root Map<String,Object> expectedResult = ImmutableMap.<String,Object>of("a", ImmutableMap.of("b", "c", "@ROOT", "d")); assertEquals(result, expectedResult); } private Map<String,Object> getExpectedMapForComposeSimpleObjectWithLongerPaths() { Map<String,Object> result = new HashMap<String,Object>(); final Map<String,Object> innerMap1 = new HashMap<String,Object>() {{ put("c", ""); put("d", 42); }}; Map<String,Object> innerMap2 = new HashMap<String,Object>() {{ put("b", innerMap1); }}; result.put("a/@#", innerMap2); final Map<String,Object> innerMapF = new HashMap<String,Object>() {{ put("f", true); }}; final Map<String,Object> innerMapG = new HashMap<String,Object>() {{ put("g", false); }}; Map<String,Object> innerMapEF = new HashMap<String,Object>() {{ put("e", innerMapF); put("f", innerMapG); }}; result.put("d", innerMapEF); final Map<String,Object> innerMapL = new HashMap<String,Object>() {{ put("l", null); }}; Map<String,Object> innerMapK = new HashMap<String,Object>() {{ put("k", innerMapL); }}; result.put("j", innerMapK); return result; } }