package org.commons.jconfig.internal;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.Reader;
import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.CountDownLatch;
import org.commons.jconfig.config.ConfigContext;
import org.commons.jconfig.config.ConfigManager;
import org.commons.jconfig.config.ConfigRuntimeException;
import org.commons.jconfig.config.ConfigContext.Entry;
import org.commons.jconfig.internal.ConfigManagerCache;
import org.testng.Assert;
import org.testng.annotations.Test;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.google.gson.JsonParser;
/**
* Test functionality of {@link ConfigManagerCache} by inserting and fetching
* value
*
* @author jaikit
*
*/
@Test(singleThreaded = false)
public class ConfigManagerCacheTest {
ConfigManagerCache threadSafeAdapter = new ConfigManagerCache(ConfigManager.INSTANCE);
List<Object> module = new ArrayList<Object>();
public JsonObject getTestJson(String fileName) throws IOException {
File config = new File(fileName);
FileInputStream in = new FileInputStream(config);
Reader reader = new BufferedReader(new InputStreamReader(in, Charset.forName("utf-8")));
JsonParser parser = new JsonParser();
JsonObject json = (JsonObject) parser.parse(reader);
reader.close();
in.close();
reader = null;
return json;
}
@Test
public void insertValueValid() throws IOException {
ConfigManagerCache adapter = new ConfigManagerCache(ConfigManager.INSTANCE);
JsonObject json = getTestJson("./src/test/resources/configFormatAdapter.json");
JsonElement test1 = json.get("Test1");
// use module name as ConfigFormatLoaderAdapter name
for (JsonElement node : test1.getAsJsonArray()) {
adapter.insertValue(adapter.getClass().getName(), node.toString());
}
adapter.flipCache();
ConfigContext context1 = new ConfigContext(new Entry("COLO", "bf1"));
Assert.assertEquals(adapter.get(adapter, context1, "SonoraHostname", ""), "stage1.sonora.bf1.xyz.com");
Assert.assertEquals(adapter.get(adapter, context1, "SonoraAppId", ""), "invalidappid");
ConfigContext context2 = new ConfigContext(new Entry("COLO", "ne1"));
Assert.assertEquals(adapter.get(adapter, context2, "SonoraHostname", ""), "stage1.sonora.ne1.xyz.com");
Assert.assertEquals(adapter.get(adapter, context2, "SonoraAppId", ""), "yca.stage.app.id.ne1");
ConfigContext context3 = new ConfigContext(new Entry("COLO", "invalid"));
Assert.assertEquals(adapter.get(adapter, context3, "SonoraHostname", ""), "localhost");
Assert.assertEquals(adapter.get(adapter, context3, "SonoraAppId", ""), "invalidappid");
ConfigContext context4 = new ConfigContext(new Entry("COLO", "ac1"));
Assert.assertEquals(adapter.get(adapter, context4, "SonoraHostname", ""), "stage1.sonora.ne1.xyz.com");
Assert.assertEquals(adapter.get(adapter, context4, "SonoraAppId", ""), "yca.stage.app.id.ac1");
}
/**
* Verifies that test throws {@link ConfigRuntimeException} because it tries
* to insert 2 settype values for same module
*/
@Test(expectedExceptions = ConfigRuntimeException.class)
public void insertValueInvalid() throws IOException {
ConfigManagerCache adapter = new ConfigManagerCache(ConfigManager.INSTANCE);
JsonObject json = getTestJson("./src/test/resources/configFormatAdapter.json");
JsonElement test1 = json.get("Test2");
// use module name as ConfigFormatLoaderAdapter name
for (JsonElement node : test1.getAsJsonArray()) {
adapter.insertValue(adapter.getClass().getName(), node.toString());
}
}
@Test
public void inserValueMultipleModules() throws IOException {
ConfigManagerCache adapter = new ConfigManagerCache(ConfigManager.INSTANCE);
JsonObject json = getTestJson("./src/test/resources/configFormatAdapter.json");
JsonElement test1 = json.get("Test1");
JsonElement test3 = json.get("Test3");
// use module name as ConfigFormatLoaderAdapter name
for (JsonElement node : test1.getAsJsonArray()) {
adapter.insertValue(adapter.getClass().getName(), node.toString());
}
Object obj = new Object();
// use module name as java Object name
for (JsonElement node : test3.getAsJsonArray()) {
adapter.insertValue(obj.getClass().getName(), node.toString());
}
adapter.flipCache();
ConfigContext context1 = new ConfigContext(new Entry("COLO", "bf1"));
Assert.assertEquals(adapter.get(adapter, context1, "SonoraHostname", ""), "stage1.sonora.bf1.xyz.com");
Assert.assertEquals(adapter.get(adapter, context1, "SonoraAppId", ""), "invalidappid");
Assert.assertEquals(adapter.get(obj, context1, "VxHostName", ""), "localhost");
// Return default value
Assert.assertEquals(adapter.get(obj, context1, "VxPortNumber", "9999"), "80");
// Value not set and hence will return default value passed in
Assert.assertEquals(adapter.get(obj, context1, "VxThreadCount", "99"), "99");
ConfigContext context2 = new ConfigContext(new Entry("COLO", "ne1"));
Assert.assertEquals(adapter.get(adapter, context2, "SonoraHostname", ""), "stage1.sonora.ne1.xyz.com");
Assert.assertEquals(adapter.get(obj, context2, "VxHostName", ""), "vxs.ne1.xyz.com");
Assert.assertEquals(adapter.get(obj, context2, "VxPortNumber", "9999"), "4080");
}
@Test
public void insertDefaultValues() throws IOException {
ConfigManagerCache adapter = new ConfigManagerCache(ConfigManager.INSTANCE);
JsonObject json = getTestJson("./src/test/resources/configFormatAdapter.json");
JsonElement test4 = json.get("Test4");
Object obj = new Object();
// use module name as java Object name
for (JsonElement node : test4.getAsJsonArray()) {
adapter.insertValue(obj.getClass().getName(), node.toString());
}
adapter.flipCache();
ConfigContext context2 = new ConfigContext();
Assert.assertEquals(adapter.get(obj, context2, "VxHostName", ""), "vxs.ne1.xyz.com");
Assert.assertEquals(adapter.get(obj, context2, "VxPortNumber", "9999"), "80");
}
@Test(invocationCount = 1000, threadPoolSize = 1000)
public void testThreadSafeClass() throws InterruptedException {
ConfigManagerCache threadSafeAdapter = new ConfigManagerCache(ConfigManager.INSTANCE);
List<Object> module = new ArrayList<Object>();
int N = 10;
CountDownLatch startSignal = new CountDownLatch(1);
CountDownLatch doneSignal = new CountDownLatch(N);
CountDownLatch start1Signal = new CountDownLatch(1);
CountDownLatch done1Signal = new CountDownLatch(N);
for (int i = 0; i < N; ++i) {
// create and start threads
new Thread(new Worker(startSignal, doneSignal, "vxs.ne1.xyz.com", threadSafeAdapter, module)).start();
}
threadSafeAdapter.insertValue(module.getClass().getName(), "{\"VxHostName\":\"vxs.ne1.xyz.com\"}");
threadSafeAdapter.flipCache();
startSignal.countDown(); // let all threads proceed
for (int i = 0; i < N; ++i)
// create and start threads
new Thread(new Worker(start1Signal, done1Signal, "vxs.ne2.xyz.com", threadSafeAdapter, module)).start();
threadSafeAdapter.insertValue(module.getClass().getName(), "{\"VxHostName\":\"vxs.ne2.xyz.com\"}");
doneSignal.await(); // wait for all to finish
threadSafeAdapter.flipCache();
start1Signal.countDown(); // let all threads proceed
done1Signal.await(); // wait for all to finish
}
class Worker implements Runnable {
private final CountDownLatch startSignal;
private final CountDownLatch doneSignal;
private final String hostname;
private final ConfigManagerCache cache;
private final List<Object> module;
Worker(CountDownLatch startSignal, CountDownLatch doneSignal, String hostname, ConfigManagerCache threadSafeAdapter, List<Object> module) {
this.startSignal = startSignal;
this.doneSignal = doneSignal;
this.hostname = hostname;
this.cache = threadSafeAdapter;
this.module = module;
}
public void run() {
try {
startSignal.await();
ConfigContext context2 = new ConfigContext();
Assert.assertEquals(this.cache.get(this.module, context2, "VxHostName", ""), this.hostname);
doneSignal.countDown();
} catch (InterruptedException ex) {
} // return;
}
}
}