/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You 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 gobblin.config.common.impl;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
import org.mockito.Mockito;
import org.testng.Assert;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.Test;
import com.typesafe.config.Config;
import com.typesafe.config.ConfigFactory;
import com.typesafe.config.ConfigValue;
import gobblin.config.store.api.ConfigKeyPath;
import gobblin.config.store.api.ConfigStore;
@Test(groups = { "gobblin.config.common.impl" })
public class TestInMemoryTopology {
private ConfigStore mockConfigStore;
private final String version = "V1.0";
private final ConfigKeyPath data = SingleLinkedListConfigKeyPath.ROOT.createChild("data");
private final ConfigKeyPath tag = SingleLinkedListConfigKeyPath.ROOT.createChild("tag");
private final ConfigKeyPath tag2 = SingleLinkedListConfigKeyPath.ROOT.createChild("tag2");
private final ConfigKeyPath databases = data.createChild("databases");
private final ConfigKeyPath identity = databases.createChild("identity");
private final ConfigKeyPath highPriorityTag = tag.createChild("highPriorityTag");
private final ConfigKeyPath espressoTag = tag.createChild("espressoTag");
private final ConfigKeyPath nertzTag2 = tag2.createChild("nertzTag2");
public void printConfig(Config config){
Set<Map.Entry<String,ConfigValue>> entrySet = config.entrySet();
for(Map.Entry<String,ConfigValue> entry: entrySet){
System.out.println("key: " + entry.getKey() + ", value: " + entry.getValue());
}
}
@BeforeClass
public void setup(){
// Topology for mock up config store
// ├── data
// │ └── databases
// │ └── identity
// ├── tag
// │ ├── espressoTag
// │ └── highPriorityTag
// └── tag2
// └── nertzTag2
mockConfigStore = mock(ConfigStore.class, Mockito.RETURNS_SMART_NULLS);
when(mockConfigStore.getCurrentVersion()).thenReturn(version);
List<ConfigKeyPath> emptyList = Collections.emptyList();
// mock up parent/children topology
List<ConfigKeyPath> rootChildren = new ArrayList<ConfigKeyPath>();
rootChildren.add(data);
rootChildren.add(tag);
rootChildren.add(tag2);
when(mockConfigStore.getChildren(SingleLinkedListConfigKeyPath.ROOT, version)).thenReturn(rootChildren);
List<ConfigKeyPath> dataChildren = new ArrayList<ConfigKeyPath>();
dataChildren.add(databases);
when(mockConfigStore.getChildren(data, version)).thenReturn(dataChildren);
List<ConfigKeyPath> databasesChildren = new ArrayList<ConfigKeyPath>();
databasesChildren.add(identity);
when(mockConfigStore.getChildren(databases, version)).thenReturn(databasesChildren);
when(mockConfigStore.getChildren(identity, version)).thenReturn(emptyList);
List<ConfigKeyPath> tagChildren = new ArrayList<ConfigKeyPath>();
tagChildren.add(highPriorityTag);
tagChildren.add(espressoTag);
when(mockConfigStore.getChildren(tag, version)).thenReturn(tagChildren);
when(mockConfigStore.getChildren(highPriorityTag, version)).thenReturn(emptyList);
when(mockConfigStore.getChildren(espressoTag, version)).thenReturn(emptyList);
List<ConfigKeyPath> tag2Children = new ArrayList<ConfigKeyPath>();
tag2Children.add(nertzTag2);
when(mockConfigStore.getChildren(tag2, version)).thenReturn(tag2Children);
when(mockConfigStore.getChildren(nertzTag2, version)).thenReturn(emptyList);
// mock up import links
// identity import espressoTag and highPriorityTag
List<ConfigKeyPath> identityImports = new ArrayList<ConfigKeyPath>();
identityImports.add(espressoTag);
identityImports.add(highPriorityTag);
when(mockConfigStore.getOwnImports(identity, version)).thenReturn(identityImports);
// espressoTag imports nertzTag2
List<ConfigKeyPath> espressoImports = new ArrayList<ConfigKeyPath>();
espressoImports.add(nertzTag2);
when(mockConfigStore.getOwnImports(espressoTag, version)).thenReturn(espressoImports);
mockupConfigValues();
}
private void mockupConfigValues(){
// mock up the configuration values for root
Map<String, String> rootMap = new HashMap<>();
rootMap.put("keyInRoot", "valueInRoot");
when(mockConfigStore.getOwnConfig(SingleLinkedListConfigKeyPath.ROOT, version)).thenReturn(ConfigFactory.parseMap(rootMap));
Collection<ConfigKeyPath> currentLevel = mockConfigStore.getChildren(SingleLinkedListConfigKeyPath.ROOT, version);
while(!currentLevel.isEmpty()){
Collection<ConfigKeyPath> nextLevel = new ArrayList<ConfigKeyPath>();
for(ConfigKeyPath p: currentLevel){
mockupConfigValueForKey(p);
nextLevel.addAll(mockConfigStore.getChildren(p, version));
}
currentLevel = nextLevel;
}
}
private void mockupConfigValueForKey(ConfigKeyPath configKey){
final String generalKey = "generalKey";
Map<String, String> valueMap = new HashMap<>();
// key in all the nodes
valueMap.put(generalKey, "valueOf_" +generalKey +"_"+configKey.getOwnPathName() );
// key in self node
valueMap.put("keyOf_" + configKey.getOwnPathName(), "valueOf_" + configKey.getOwnPathName());
when(mockConfigStore.getOwnConfig(configKey, version)).thenReturn(ConfigFactory.parseMap(valueMap));
}
@Test
public void testNonRootTopology() {
Assert.assertEquals(mockConfigStore.getCurrentVersion(), version);
ConfigStoreBackedTopology csTopology = new ConfigStoreBackedTopology(this.mockConfigStore, this.version);
InMemoryTopology inMemory = new InMemoryTopology(csTopology);
Collection<ConfigKeyPath> result = inMemory.getChildren(data);
Assert.assertTrue(result.size()==1);
Assert.assertEquals(result.iterator().next(), databases);
// test own imports
result = inMemory.getOwnImports(identity);
Assert.assertTrue(result.size()==2);
Iterator<ConfigKeyPath> it = result.iterator();
Assert.assertEquals(it.next(), espressoTag);
Assert.assertEquals(it.next(), highPriorityTag);
// test import recursively
result = inMemory.getImportsRecursively(identity);
Assert.assertTrue(result.size()==3);
it = result.iterator();
Assert.assertEquals(it.next(), espressoTag);
Assert.assertEquals(it.next(), nertzTag2);
Assert.assertEquals(it.next(), highPriorityTag);
// test own imported by
result = inMemory.getImportedBy(nertzTag2);
Assert.assertTrue(result.size()==1);
Assert.assertEquals(result.iterator().next(), espressoTag);
// test imported by recursively, as the imported by recursively do not care about
// order, need to use HashSet to test
result = inMemory.getImportedByRecursively(nertzTag2);
Set<ConfigKeyPath> expected = new HashSet<ConfigKeyPath>();
expected.add(espressoTag);
expected.add(identity);
Assert.assertTrue(result.size()==2);
it = result.iterator();
while(it.hasNext()){
ConfigKeyPath tmp = it.next();
Assert.assertTrue(expected.contains(tmp));
expected.remove(tmp);
}
}
@Test
public void testNonRootValues() {
ConfigStoreBackedTopology csTopology = new ConfigStoreBackedTopology(this.mockConfigStore, this.version);
InMemoryTopology inMemory = new InMemoryTopology(csTopology);
ConfigStoreBackedValueInspector rawValueInspector = new ConfigStoreBackedValueInspector(this.mockConfigStore, this.version, inMemory);
InMemoryValueInspector inMemoryStrongRef = new InMemoryValueInspector(rawValueInspector, true);
InMemoryValueInspector inMemoryWeakRef = new InMemoryValueInspector(rawValueInspector, false);
// test values for Identity
testValuesForIdentity(rawValueInspector);
testValuesForIdentity(inMemoryStrongRef);
testValuesForIdentity(inMemoryWeakRef);
// test values for Espresso Tag
testValuesForEspressoTag(rawValueInspector);
testValuesForEspressoTag(inMemoryStrongRef);
testValuesForEspressoTag(inMemoryWeakRef);
// test for batch
Collection<ConfigKeyPath> inputs = new ArrayList<ConfigKeyPath>();
inputs.add(espressoTag);
inputs.add(identity);
Map<ConfigKeyPath, Config> resultMap = rawValueInspector.getOwnConfigs(inputs);
Assert.assertEquals(resultMap.size(), 2);
testValuesForEspressoTagOwnConfig(resultMap.get(espressoTag));
checkValuesForIdentityOwnConfig(resultMap.get(identity));
resultMap = rawValueInspector.getResolvedConfigs(inputs);
Assert.assertEquals(resultMap.size(), 2);
testValuesForEspressoTagResolvedConfig(resultMap.get(espressoTag));
checkValuesForIdentityResolvedConfig(resultMap.get(identity));
}
private void testValuesForEspressoTag(ConfigStoreValueInspector valueInspector){
Config config = valueInspector.getOwnConfig(this.espressoTag);
testValuesForEspressoTagOwnConfig(config);
config = valueInspector.getResolvedConfig(this.espressoTag);
testValuesForEspressoTagResolvedConfig(config);
}
private void testValuesForEspressoTagOwnConfig(Config config){
Assert.assertTrue(config.getString("keyOf_espressoTag").equals("valueOf_espressoTag"));
Assert.assertTrue(config.getString("generalKey").equals("valueOf_generalKey_espressoTag"));
}
private void testValuesForEspressoTagResolvedConfig(Config config){
Assert.assertTrue(config.getString("keyOf_espressoTag").equals("valueOf_espressoTag"));
Assert.assertTrue(config.getString("generalKey").equals("valueOf_generalKey_espressoTag"));
Assert.assertTrue(config.getString("keyInRoot").equals("valueInRoot"));
Assert.assertTrue(config.getString("keyOf_nertzTag2").equals("valueOf_nertzTag2"));
Assert.assertTrue(config.getString("keyOf_tag2").equals("valueOf_tag2"));
Assert.assertTrue(config.getString("keyOf_tag").equals("valueOf_tag"));
}
private void testValuesForIdentity(ConfigStoreValueInspector valueInspector){
Config ownConfig = valueInspector.getOwnConfig(identity);
checkValuesForIdentityOwnConfig(ownConfig);
Config resolvedConfig = valueInspector.getResolvedConfig(identity);
checkValuesForIdentityResolvedConfig(resolvedConfig);
}
private void checkValuesForIdentityOwnConfig(Config ownConfig){
Assert.assertTrue(ownConfig.entrySet().size() == 2 );
Assert.assertTrue(ownConfig.getString("keyOf_identity").equals("valueOf_identity"));
Assert.assertTrue(ownConfig.getString("generalKey").equals("valueOf_generalKey_identity"));
}
private void checkValuesForIdentityResolvedConfig(Config resolvedConfig){
Assert.assertTrue(resolvedConfig.getString("keyOf_data").equals("valueOf_data"));
Assert.assertTrue(resolvedConfig.getString("keyOf_identity").equals("valueOf_identity"));
Assert.assertTrue(resolvedConfig.getString("keyOf_espressoTag").equals("valueOf_espressoTag"));
Assert.assertTrue(resolvedConfig.getString("generalKey").equals("valueOf_generalKey_identity"));
Assert.assertTrue(resolvedConfig.getString("keyInRoot").equals("valueInRoot"));
Assert.assertTrue(resolvedConfig.getString("keyOf_nertzTag2").equals("valueOf_nertzTag2"));
Assert.assertTrue(resolvedConfig.getString("keyOf_highPriorityTag").equals("valueOf_highPriorityTag"));
Assert.assertTrue(resolvedConfig.getString("keyOf_tag2").equals("valueOf_tag2"));
Assert.assertTrue(resolvedConfig.getString("keyOf_tag").equals("valueOf_tag"));
Assert.assertTrue(resolvedConfig.getString("keyOf_databases").equals("valueOf_databases"));
}
}