package org.netbeans.gradle.project.properties;
import java.io.IOException;
import java.io.InputStream;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.concurrent.TimeUnit;
import org.jtrim.cancel.Cancellation;
import org.jtrim.cancel.OperationCanceledException;
import org.jtrim.collections.Equality;
import org.jtrim.concurrent.WaitableSignal;
import org.jtrim.property.MutableProperty;
import org.jtrim.property.PropertyFactory;
import org.jtrim.property.PropertySource;
import org.junit.Ignore;
import org.junit.Test;
import org.netbeans.gradle.project.api.config.ConfigPath;
import org.netbeans.gradle.project.api.config.ConfigTree;
import org.netbeans.gradle.project.api.config.PropertyDef;
import org.netbeans.gradle.project.api.config.PropertyKeyEncodingDef;
import org.netbeans.gradle.project.api.config.PropertyValueDef;
import org.netbeans.gradle.project.license.LicenseHeaderInfo;
import org.netbeans.gradle.project.properties.standard.LicenseHeaderInfoProperty;
import org.netbeans.gradle.project.properties.standard.PlatformId;
import org.netbeans.gradle.project.properties.standard.TargetPlatformProperty;
import static org.junit.Assert.*;
public class ProfileSettingsTest {
private static void readDocument(ProfileSettings settings, String configFileName) throws IOException {
try (InputStream input = TestResourceUtils.openResource(configFileName)) {
settings.loadFromStream(input);
}
}
private static void readFromSettings1(ProfileSettings settings) throws IOException {
readDocument(settings, "settings1.xml");
}
private static ConfigPath getConfigPath(String... keys) {
return ConfigPath.fromKeys(Arrays.asList(keys));
}
private static void setSimpleEncodingDef(PropertyDef.Builder<ConfigTree, ?> result) {
result.setKeyEncodingDef(new PropertyKeyEncodingDef<ConfigTree>() {
@Override
public ConfigTree decode(ConfigTree config) {
return config;
}
@Override
public ConfigTree encode(ConfigTree value) {
return value;
}
});
}
private static PropertyDef<PlatformId, PlatformId> getTargetPlatformProfileDef(
Collection<ConfigPath> configPaths) {
PropertyDef.Builder<PlatformId, PlatformId> result = new PropertyDef.Builder<>(configPaths);
result.setValueDef(new PropertyValueDef<PlatformId, PlatformId>() {
@Override
public PropertySource<PlatformId> property(PlatformId valueKey) {
return PropertyFactory.constSource(valueKey);
}
@Override
public PlatformId getKeyFromValue(PlatformId value) {
return value;
}
});
result.setKeyEncodingDef(TargetPlatformProperty.PROPERTY_DEF.getKeyEncodingDef());
return result.create();
}
private static PropertyDef<ConfigTree, String> getTextProfileDef(
Collection<ConfigPath> configPaths,
boolean naturalEquals) {
PropertyDef.Builder<ConfigTree, String> result = new PropertyDef.Builder<>(configPaths);
result.setValueDef(new PropertyValueDef<ConfigTree, String>() {
@Override
public PropertySource<String> property(ConfigTree valueKey) {
return PropertyFactory.constSource(valueKey != null
? valueKey.getValue(null)
: null);
}
@Override
public ConfigTree getKeyFromValue(String value) {
if (value == null) {
return null;
}
return ConfigTree.singleValue(value);
}
});
if (!naturalEquals) {
result.setValueKeyEquality(Equality.referenceEquality());
}
setSimpleEncodingDef(result);
return result.create();
}
private static MutableProperty<String> getTextProperty(
ProfileSettings settings,
String... keys) {
return getTextProperty(settings, true, keys);
}
private static MutableProperty<String> getTextProperty(
ProfileSettings settings,
boolean naturalEquals,
String... keys) {
ConfigPath configPath = getConfigPath(keys);
Collection<ConfigPath> configPaths = Collections.singleton(configPath);
return settings.getProperty(getTextProfileDef(configPaths, naturalEquals));
}
private void testSetValueOfTextProperty(
String initialValue,
String newValue,
String... propertyPath) throws IOException {
testSetValueOfTextProperty(initialValue, newValue, true, propertyPath);
}
private void testSetValueOfTextProperty(
String initialValue,
String newValue,
boolean naturalEquals,
String... propertyPath) throws IOException {
ProfileSettings settings = new ProfileSettings();
readFromSettings1(settings);
String propertyName = Arrays.toString(propertyPath);
MutableProperty<String> property = getTextProperty(settings, naturalEquals, propertyPath);
assertEquals(propertyName, initialValue, property.getValue());
WaitableListener documentListener = new WaitableListener();
settings.addDocumentChangeListener(documentListener);
WaitableListener listener = new WaitableListener();
property.addChangeListener(listener);
property.setValue(newValue);
assertEquals(propertyName, newValue, property.getValue());
listener.waitForCall("Value change for text node.");
documentListener.waitForCall("Document change for text node.");
}
@Test(timeout = 30000)
public void testSetValueOfRootTextPropertyWithReferenceComparison() throws IOException {
testSetValueOfTextProperty("UTF-8", "ISO-8859-1", false, "source-encoding");
testSetValueOfTextProperty("j2se", "j2me", false, "target-platform-name");
testSetValueOfTextProperty("1.7", "1.6", false, "target-platform");
testSetValueOfTextProperty("1.7", "1.8", false, "source-level");
}
@Test
public void testSetValueOfRootTextProperty() throws IOException {
for (int i = 0; i < 100; i++) {
testSetValueOfTextProperty("UTF-8", "ISO-8859-1", "source-encoding");
}
testSetValueOfTextProperty("j2se", "j2me", "target-platform-name");
testSetValueOfTextProperty("1.7", "1.6", "target-platform");
testSetValueOfTextProperty("1.7", "1.8", "source-level");
}
@Test
public void testSetValueOfDeepTextProperty() throws IOException {
for (int i = 0; i < 100; i++) {
testSetValueOfTextProperty("Value0", "Value1", "custom-group", "custom-node");
}
}
@Test
public void testSetValueOfDeepTextPropertyWithReferenceComparison() throws IOException {
testSetValueOfTextProperty("Value0", "Value1", false, "custom-group", "custom-node");
}
private void testLoadFromFileLater(String expectedValue, String... propertyPath) throws IOException {
ProfileSettings settings = new ProfileSettings();
MutableProperty<String> property = getTextProperty(settings, propertyPath);
readFromSettings1(settings);
assertEquals(Arrays.toString(propertyPath), expectedValue, property.getValue());
}
@Test
public void testLoadFromFileLater() throws IOException {
testLoadFromFileLater("UTF-8","source-encoding");
testLoadFromFileLater("j2se", "target-platform-name");
testLoadFromFileLater("1.7", "target-platform");
testLoadFromFileLater("1.7", "source-level");
}
// This test must be redesigned because target platform now cannot be fooled.
@Ignore
@Test
public void testIntersectingMultiNodeProperties() throws IOException {
ProfileSettings settings = new ProfileSettings();
readFromSettings1(settings);
List<ConfigPath> configPaths1 = Arrays.asList(
getConfigPath("target-platform-name"),
getConfigPath("target-platform"));
List<ConfigPath> configPaths2 = Arrays.asList(
getConfigPath("target-platform-name"),
getConfigPath("source-level"));
MutableProperty<PlatformId> property1
= settings.getProperty(getTargetPlatformProfileDef(configPaths1));
MutableProperty<PlatformId> property2
= settings.getProperty(getTargetPlatformProfileDef(configPaths2));
PlatformId propert1Initial = new PlatformId("j2se", "1.7");
PlatformId propert2Initial = propert1Initial;
assertEquals(propert1Initial, property1.getValue());
assertEquals(propert2Initial, property2.getValue());
property1.setValue(new PlatformId("j2me", "1.5"));
assertEquals(new PlatformId("j2me", "1.7"), property2.getValue());
}
@Test
public void testLicenseHeaderInfoInSettings1() throws IOException {
ProfileSettings settings = new ProfileSettings();
readFromSettings1(settings);
MutableProperty<LicenseHeaderInfo> license = settings.getProperty(LicenseHeaderInfoProperty.PROPERTY_DEF);
LicenseHeaderInfo value = license.getValue();
assertNotNull("LicenseHeaderInfo", value);
assertEquals("LicenseName", "my-license", value.getLicenseName());
assertEquals("organization", Collections.singletonMap("organization", "MyCompany"), value.getProperties());
assertEquals("FileName", "license2.txt", value.getLicenseTemplateFile().getFileName().toString());
license.setValue(null);
assertNull("LicenseHeaderInfo", license.getValue());
}
@Test
public void testMultiNodeProperty() throws IOException {
ProfileSettings settings = new ProfileSettings();
readFromSettings1(settings);
List<ConfigPath> configPaths = Arrays.asList(
getConfigPath("target-platform-name"),
getConfigPath("target-platform"));
MutableProperty<PlatformId> property
= settings.getProperty(getTargetPlatformProfileDef(configPaths));
String propertyName = "TargetPlatform";
assertEquals(propertyName, new PlatformId("j2se", "1.7"), property.getValue());
WaitableListener documentListener = new WaitableListener();
settings.addDocumentChangeListener(documentListener);
WaitableListener listener = new WaitableListener();
property.addChangeListener(listener);
PlatformId newValue = new PlatformId("j2me", "1.5");
property.setValue(newValue);
assertEquals(propertyName, newValue, property.getValue());
listener.waitForCall("Value change for multi node.");
documentListener.waitForCall("Document change for multi node.");
}
private static final class WaitableListener implements Runnable {
private final WaitableSignal calledSignal;
public WaitableListener() {
this.calledSignal = new WaitableSignal();
}
@Override
public void run() {
calledSignal.signal();
}
public void waitForCall(String taskName) {
if (!calledSignal.tryWaitSignal(Cancellation.UNCANCELABLE_TOKEN, 10, TimeUnit.SECONDS)) {
throw new OperationCanceledException("Timeout: " + taskName);
}
}
}
}