package co.codewizards.cloudstore.core.config;
import static co.codewizards.cloudstore.core.io.StreamUtil.*;
import static co.codewizards.cloudstore.core.oio.OioFileFactory.*;
import static org.assertj.core.api.Assertions.*;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.Properties;
import org.junit.Test;
import co.codewizards.cloudstore.core.oio.File;
import co.codewizards.cloudstore.core.repo.local.LocalRepoManager;
import co.codewizards.cloudstore.core.repo.local.LocalRepoManagerFactory;
import co.codewizards.cloudstore.core.repo.transport.FileWriteStrategy;
import co.codewizards.cloudstore.core.util.AssertUtil;
import co.codewizards.cloudstore.local.AbstractTest;
public class ConfigTest extends AbstractTest {
private static final Object mutex = ConfigTest.class;
/**
* Tests whether the global configuration file is named as documented on the
* web-site. If this test breaks, it must be verified, if the name really needs to be changed
* and if so, the documentation must be updated together with this test!!!
*/
@Test
public void testGlobalConfigFileName() throws Exception {
synchronized (mutex) {
final ConfigImpl globalConfig = (ConfigImpl) ConfigImpl.getInstance();
assertThat(globalConfig.propertiesFiles.length).isEqualTo(1);
assertThat(globalConfig.propertiesFiles[0]).isNotNull();
assertThat(globalConfig.propertiesFiles[0].getName()).isEqualTo("cloudstore.properties");
deleteMainConfigFiles();
}
}
@Test
public void testGlobalConfigFileModification() throws Exception {
synchronized (mutex) {
final Config globalConfig = ConfigImpl.getInstance();
final String testKey = "testKey0";
String value = globalConfig.getProperty(testKey, null);
assertThat(value).isNull();
long version1 = globalConfig.getVersion();
waitForDifferentLastModifiedTimestamp();
setGlobalProperty(testKey, "testValueAAA");
value = globalConfig.getProperty(testKey, null);
assertThat(value).isEqualTo("testValueAAA");
long version2 = globalConfig.getVersion();
assertThat(version1).isNotEqualTo(version2);
waitForDifferentLastModifiedTimestamp();
setGlobalProperty(testKey, "testValueBBB");
value = globalConfig.getProperty(testKey, null);
assertThat(value).isEqualTo("testValueBBB");
version1 = globalConfig.getVersion();
assertThat(version1).isNotEqualTo(version2);
deleteMainConfigFiles();
}
}
@Test
public void testConfigInheritance() throws Exception {
synchronized (mutex) {
final String testKey1 = "testKey1";
final String testKey2 = "testKey2";
final File localRoot = newTestRepositoryLocalRoot();
assertThat(localRoot.exists()).isFalse();
localRoot.mkdirs();
assertThat(localRoot.isDirectory()).isTrue();
try (final LocalRepoManager localRepoManager = LocalRepoManagerFactory.Helper.getInstance().createLocalRepoManagerForNewRepository(localRoot);) {
assertThat(localRepoManager).isNotNull();
final File child_1 = createFile(localRoot, "1_" + random.nextInt(10000));
assertThat(child_1.exists()).isFalse();
final Config config_1 = ConfigImpl.getInstanceForDirectory(child_1);
assertThat(config_1.getPropertyAsNonEmptyTrimmedString(testKey1, null)).isNull();
createDirectory(child_1);
assertThat(child_1.isDirectory()).isTrue();
setProperty(createFile(child_1, ".cloudstore.properties"), testKey1, " testValueAAA ");
assertThat(config_1.getPropertyAsNonEmptyTrimmedString(testKey1, null)).isEqualTo("testValueAAA");
setProperty(createFile(child_1, "cloudstore.properties"), testKey1, " testValueBBB ");
assertThat(config_1.getPropertyAsNonEmptyTrimmedString(testKey1, null)).isEqualTo("testValueBBB");
assertThat(config_1.getPropertyAsEnum(FileWriteStrategy.CONFIG_KEY, FileWriteStrategy.directAfterTransfer)).isEqualTo(FileWriteStrategy.directAfterTransfer);
assertThat(config_1.getPropertyAsEnum(FileWriteStrategy.CONFIG_KEY, FileWriteStrategy.class, null)).isNull();
long version1 = config_1.getVersion();
waitForDifferentLastModifiedTimestamp();
setGlobalProperty(FileWriteStrategy.CONFIG_KEY, FileWriteStrategy.replaceAfterTransfer.name());
assertThat(config_1.getPropertyAsEnum(FileWriteStrategy.CONFIG_KEY, FileWriteStrategy.directAfterTransfer)).isEqualTo(FileWriteStrategy.replaceAfterTransfer);
long version2 = config_1.getVersion();
assertThat(version1).isNotEqualTo(version2);
final File child_1_a = createFile(child_1, "a");
final Config config_1_a = ConfigImpl.getInstanceForFile(child_1_a);
assertThat(config_1_a.getPropertyAsEnum(FileWriteStrategy.CONFIG_KEY, FileWriteStrategy.directAfterTransfer)).isEqualTo(FileWriteStrategy.replaceAfterTransfer);
assertThat(config_1_a.getPropertyAsNonEmptyTrimmedString(testKey1, null)).isEqualTo("testValueBBB");
waitForDifferentLastModifiedTimestamp();
setProperty(createFile(child_1, ".a.cloudstore.properties"), testKey1, "testValueCCC");
setProperty(createFile(child_1, ".a.cloudstore.properties"), FileWriteStrategy.CONFIG_KEY, FileWriteStrategy.directDuringTransfer.name());
assertThat(config_1_a.getPropertyAsNonEmptyTrimmedString(testKey1, null)).isEqualTo("testValueCCC");
assertThat(config_1_a.getPropertyAsEnum(FileWriteStrategy.CONFIG_KEY, FileWriteStrategy.directAfterTransfer)).isEqualTo(FileWriteStrategy.directDuringTransfer);
setProperty(createFile(child_1, "a.cloudstore.properties"), testKey1, " testValueDDD ");
assertThat(config_1_a.getPropertyAsNonEmptyTrimmedString(testKey1, null)).isEqualTo("testValueDDD");
waitForDifferentLastModifiedTimestamp();
setProperty(createFile(child_1, "a.cloudstore.properties"), testKey1, " ");
assertThat(config_1_a.getPropertyAsNonEmptyTrimmedString(testKey1, "xxxyyyzzz")).isEqualTo("xxxyyyzzz");
assertThat(config_1_a.getProperty(testKey1, "xxxyyyzzz")).isEqualTo(" ");
waitForDifferentLastModifiedTimestamp();
setProperty(createFile(child_1, "a.cloudstore.properties"), testKey1, null);
assertThat(config_1_a.getPropertyAsNonEmptyTrimmedString(testKey1, "xxxyyyzzz")).isEqualTo("testValueCCC");
createFileWithRandomContent(child_1_a);
final File child_1_2 = createDirectory(child_1, "2");
final File child_1_2_aaa = createFile(child_1_2, "aaa");
createFileWithRandomContent(child_1_2_aaa);
final Config config_1_2_aaa = ConfigImpl.getInstanceForFile(child_1_2_aaa);
assertThat(config_1_2_aaa.getPropertyAsNonEmptyTrimmedString(testKey1, "xxxyyyzzz")).isEqualTo("testValueBBB");
setProperty(createFile(child_1_2_aaa.getParentFile(), ".cloudstore.properties"), testKey1, "val_1_2_hidden");
assertThat(config_1_2_aaa.getProperty(testKey1, null)).isEqualTo("val_1_2_hidden");
setProperty(createFile(child_1_2_aaa.getParentFile(), "cloudstore.properties"), testKey1, "val_1_2_visible");
assertThat(config_1_2_aaa.getProperty(testKey1, null)).isEqualTo("val_1_2_visible");
assertThat(config_1_2_aaa.getPropertyAsEnum(FileWriteStrategy.CONFIG_KEY, FileWriteStrategy.directAfterTransfer)).isEqualTo(FileWriteStrategy.replaceAfterTransfer); // global
setProperty(createFile(localRoot, "cloudstore.properties"), FileWriteStrategy.CONFIG_KEY, FileWriteStrategy.directDuringTransfer.name());
assertThat(config_1_2_aaa.getPropertyAsEnum(FileWriteStrategy.CONFIG_KEY, FileWriteStrategy.directAfterTransfer)).isEqualTo(FileWriteStrategy.directDuringTransfer); // root directory
setProperty(createFile(child_1_2_aaa.getParentFile(), "aaa.cloudstore.properties"), testKey1, "val_1_2_aaa_visible");
assertThat(config_1_2_aaa.getProperty(testKey1, null)).isEqualTo("val_1_2_aaa_visible");
waitForDifferentLastModifiedTimestamp();
setProperty(createFile(child_1_2_aaa.getParentFile(), ".cloudstore.properties"), FileWriteStrategy.CONFIG_KEY, FileWriteStrategy.directAfterTransfer.name());
assertThat(config_1_2_aaa.getPropertyAsEnum(FileWriteStrategy.CONFIG_KEY, FileWriteStrategy.directAfterTransfer)).isEqualTo(FileWriteStrategy.directAfterTransfer);
waitForDifferentLastModifiedTimestamp();
setProperty(createFile(child_1_2_aaa.getParentFile(), ".cloudstore.properties"), FileWriteStrategy.CONFIG_KEY, "");
assertThat(config_1_2_aaa.getPropertyAsEnum(FileWriteStrategy.CONFIG_KEY, FileWriteStrategy.class, null)).isNull();
waitForDifferentLastModifiedTimestamp();
setProperty(createFile(child_1_2_aaa.getParentFile(), "aaa.cloudstore.properties"), FileWriteStrategy.CONFIG_KEY, FileWriteStrategy.directDuringTransfer.name());
assertThat(config_1_2_aaa.getPropertyAsEnum(FileWriteStrategy.CONFIG_KEY, FileWriteStrategy.class, null)).isEqualTo(FileWriteStrategy.directDuringTransfer);
waitForDifferentLastModifiedTimestamp();
setProperty(createFile(child_1_2_aaa.getParentFile(), "aaa.cloudstore.properties"), FileWriteStrategy.CONFIG_KEY, null);
assertThat(config_1_2_aaa.getPropertyAsEnum(FileWriteStrategy.CONFIG_KEY, FileWriteStrategy.class, null)).isNull();
setProperty(createFile(child_1_2_aaa.getParentFile(), ".cloudstore.properties"), FileWriteStrategy.CONFIG_KEY, null);
assertThat(config_1_2_aaa.getPropertyAsEnum(FileWriteStrategy.CONFIG_KEY, FileWriteStrategy.class, null)).isEqualTo(FileWriteStrategy.directDuringTransfer);
setProperty(createFile(child_1, "cloudstore.properties"), testKey2, " 55588 ");
assertThat(config_1_2_aaa.getPropertyAsLong(testKey2, -1)).isEqualTo(55588);
deleteMainConfigFiles();
}
}
}
private void deleteMainConfigFiles() {
for (final File file : ((ConfigImpl) ConfigImpl.getInstance()).propertiesFiles) {
file.delete();
assertThat(file.exists()).isFalse();
}
}
private static void waitForDifferentLastModifiedTimestamp() {
// Make sure the file has a different lastModified-timestamp! Most file systems have a timestamp-granularity of 1 second.
try {
Thread.sleep(1100);
} catch (final InterruptedException e) {
throw new RuntimeException(e);
}
}
private File newTestRepositoryLocalRoot() throws IOException {
return newTestRepositoryLocalRoot("");
}
private static void setGlobalProperty(final String key, final String value) throws IOException {
setProperty(((ConfigImpl) ConfigImpl.getInstance()).propertiesFiles[0], key, value);
}
private static void setProperty(final File propertiesFile, final String key, final String value) throws IOException {
AssertUtil.assertNotNull(propertiesFile, "propertiesFile");
AssertUtil.assertNotNull(key, "key");
final Properties properties = new Properties();
if (propertiesFile.exists()) {
final InputStream in = castStream(propertiesFile.createInputStream());
properties.load(in);
in.close();
}
if (value == null)
properties.remove(key);
else
properties.setProperty(key, value);
final OutputStream out = castStream(propertiesFile.createOutputStream());
properties.store(out, null);
out.close();
}
}