blob: e7ff91b23da1848b1d99999c4baee1e29a9f4365 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2004, 2018 IBM Corporation and others.
*
* This program and the accompanying materials
* are made available under the terms of the Eclipse Public License 2.0
* which accompanies this distribution, and is available at
* https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*
* Contributors:
* IBM Corporation - initial API and implementation
* Semion Chichelnitsky (semion@il.ibm.com) - bug 208564
*******************************************************************************/
package org.eclipse.core.tests.internal.preferences;
import java.io.*;
import java.util.*;
import org.eclipse.core.internal.preferences.EclipsePreferences;
import org.eclipse.core.runtime.*;
import org.eclipse.core.runtime.preferences.*;
import org.eclipse.core.tests.runtime.RuntimeTest;
import org.eclipse.core.tests.runtime.RuntimeTestsPlugin;
import org.osgi.service.prefs.BackingStoreException;
import org.osgi.service.prefs.Preferences;
/**
* @since 3.0
*/
public class PreferencesServiceTest extends RuntimeTest {
static class ExportVerifier {
private IEclipsePreferences node;
private ByteArrayOutputStream output;
private Set<String> expected;
private String[] excludes;
private IPreferenceFilter[] transfers;
private boolean useTransfers;
public ExportVerifier(IEclipsePreferences node, String[] excludes) {
super();
this.node = node;
this.excludes = excludes;
this.expected = new HashSet<>();
}
public ExportVerifier(IEclipsePreferences node, IPreferenceFilter[] transfers) {
super();
this.node = node;
this.transfers = transfers;
this.expected = new HashSet<>();
this.useTransfers = true;
}
void addExpected(String path, String key) {
this.expected.add(EclipsePreferences.encodePath(path, key));
}
void addVersion() {
expected.add("file_export_version");
}
void setExcludes(String[] excludes) {
this.excludes = excludes;
}
void addExportRoot(IEclipsePreferences root) {
expected.add('!' + root.absolutePath());
}
void verify() {
IPreferencesService service = Platform.getPreferencesService();
this.output = new ByteArrayOutputStream();
try {
if (useTransfers) {
service.exportPreferences(node, transfers, output);
} else {
service.exportPreferences(node, output, excludes);
}
} catch (CoreException e) {
fail("0.0", e);
}
ByteArrayInputStream input = new ByteArrayInputStream(output.toByteArray());
Properties properties = new Properties();
try {
properties.load(input);
} catch (IOException e) {
fail("1.0", e);
} finally {
try {
input.close();
} catch (IOException e) {
// ignore
}
}
if (properties.isEmpty()) {
assertTrue("2.0", expected.isEmpty());
return;
}
assertEquals("3.0", expected.size(), properties.size());
for (String key : expected) {
assertNotNull("4.0." + key, properties.get(key));
}
}
}
public PreferencesServiceTest(String name) {
super(name);
}
public void testImportExportBasic() {
IPreferencesService service = Platform.getPreferencesService();
// create test node hierarchy
String qualifier = getUniqueString() + '1';
IEclipsePreferences test = new TestScope().getNode(qualifier);
String key = getUniqueString() + 'k';
String value = getUniqueString() + 'v';
String key1 = "http://eclipse.org:24";
String value1 = getUniqueString() + "v1";
String actual = test.get(key, null);
assertNull("1.0", actual);
test.put(key, value);
test.put(key1, value1);
actual = test.get(key, null);
assertEquals("1.1", value, actual);
actual = test.get(key1, null);
assertEquals("1.2", value1, actual);
// export it
ByteArrayOutputStream output = new ByteArrayOutputStream();
try {
service.exportPreferences(test, output, (String[]) null);
} catch (CoreException e) {
fail("2.0", e);
} finally {
try {
output.close();
} catch (IOException e1) {
// ignore
}
}
byte[] bytes = output.toByteArray();
// add new values
String newKey = getUniqueString() + '3';
String newValue = getUniqueString() + '4';
actual = test.get(newKey, null);
assertNull("3.0", actual);
test.put(newKey, newValue);
actual = test.get(newKey, null);
assertEquals("3.1", newValue, actual);
String newOldValue = getUniqueString() + '5';
test.put(key, newOldValue);
actual = test.get(key, null);
assertEquals("3.2", newOldValue, actual);
// import
ByteArrayInputStream input = new ByteArrayInputStream(bytes);
try {
service.importPreferences(input);
} catch (CoreException e) {
fail("4.0", e);
} finally {
try {
input.close();
} catch (IOException e) {
// ignore
}
}
// verify
test = new TestScope().getNode(qualifier);
actual = test.get(key, null);
assertEquals("5.0", value, actual);
actual = test.get(key1, null);
assertEquals("5.1", value1, actual);
actual = test.get(newKey, null);
assertNull("5.2", actual);
// ensure that the node isn't dirty (has been saved after the import)
assertTrue("5.3", test instanceof EclipsePreferences);
assertTrue("5.4", !((EclipsePreferences) test).isDirty());
// clear all
try {
test.clear();
} catch (BackingStoreException e) {
fail("6.0", e);
}
actual = test.get(key, null);
assertNull("6.1", actual);
actual = test.get(key1, null);
assertNull("6.2", actual);
actual = test.get(newKey, null);
assertNull("6.3", actual);
// import
input = new ByteArrayInputStream(bytes);
try {
service.importPreferences(input);
} catch (CoreException e) {
fail("7.0", e);
} finally {
try {
input.close();
} catch (IOException e) {
// ignore
}
}
// verify
test = new TestScope().getNode(qualifier);
actual = test.get(key, null);
assertEquals("8.0", value, actual);
actual = test.get(key1, null);
assertEquals("8.1", value1, actual);
actual = test.get(newKey, null);
assertNull("8.2", actual);
}
private void assertEquals(String message, String[] one, String[] two) {
if (one == null && two == null) {
return;
}
if (one == two) {
return;
}
assertNotNull(message + ".1", one);
assertNotNull(message + ".2", two);
assertEquals(message + ".3", one.length, two.length);
for (int i = 0; i < one.length; i++) {
assertEquals(message + ".4." + i, one[i], two[i]);
}
}
public void testLookupOrder() {
IPreferencesService service = Platform.getPreferencesService();
String[] defaultOrder = new String[] {"project", //$NON-NLS-1$
InstanceScope.SCOPE, //
ConfigurationScope.SCOPE, //
DefaultScope.SCOPE};
String[] fullOrder = new String[] {"a", "b", "c"};
String[] nullKeyOrder = new String[] {"e", "f", "g"};
String qualifier = getUniqueString();
String key = getUniqueString();
// bogus set parms
try {
service.setDefaultLookupOrder(null, key, fullOrder);
fail("0.0");
} catch (IllegalArgumentException e) {
// expected
}
try {
service.setDefaultLookupOrder(qualifier, key, new String[] {"a", null, "b"});
fail("0.1");
} catch (IllegalArgumentException e) {
// expected
}
// nothing set
String[] order = service.getDefaultLookupOrder(qualifier, key);
assertNull("1.0", order);
order = service.getLookupOrder(qualifier, key);
assertNotNull("1.1", order);
assertEquals("1.2", defaultOrder, order);
order = service.getDefaultLookupOrder(qualifier, null);
assertNull("1.3", order);
order = service.getLookupOrder(qualifier, null);
assertNotNull("1.4", order);
assertEquals("1.5", defaultOrder, order);
// set for qualifier/key
service.setDefaultLookupOrder(qualifier, key, fullOrder);
order = service.getDefaultLookupOrder(qualifier, key);
assertNotNull("2.2", order);
assertEquals("2.3", fullOrder, order);
order = service.getLookupOrder(qualifier, key);
assertNotNull("2.4", order);
assertEquals("2.5", fullOrder, order);
// nothing set for qualifier/null
order = service.getDefaultLookupOrder(qualifier, null);
assertNull("3.0", order);
order = service.getLookupOrder(qualifier, null);
assertNotNull("3.1", order);
assertEquals("3.2", defaultOrder, order);
// set for qualifier/null
service.setDefaultLookupOrder(qualifier, null, nullKeyOrder);
order = service.getDefaultLookupOrder(qualifier, null);
assertNotNull("4.0", order);
assertEquals("4.1", nullKeyOrder, order);
order = service.getLookupOrder(qualifier, null);
assertNotNull("4.2", order);
assertEquals("4.3", nullKeyOrder, order);
order = service.getDefaultLookupOrder(qualifier, key);
assertNotNull("4.4", order);
assertEquals("4.5", fullOrder, order);
order = service.getLookupOrder(qualifier, key);
assertNotNull("4.6", order);
assertEquals("4.7", fullOrder, order);
// clear qualifier/key (find qualifier/null)
service.setDefaultLookupOrder(qualifier, key, null);
order = service.getDefaultLookupOrder(qualifier, key);
assertNull("5.0", order);
order = service.getLookupOrder(qualifier, key);
assertNotNull("5.1", order);
assertEquals("5.2", nullKeyOrder, order);
// clear qualifier/null (find returns default-default)
service.setDefaultLookupOrder(qualifier, null, null);
order = service.getDefaultLookupOrder(qualifier, key);
assertNull("6.0", order);
order = service.getLookupOrder(qualifier, key);
assertNotNull("6.1", order);
assertEquals("6.2", defaultOrder, order);
order = service.getDefaultLookupOrder(qualifier, null);
assertNull("6.3", order);
order = service.getLookupOrder(qualifier, null);
assertNotNull("6.4", order);
assertEquals("6.5", defaultOrder, order);
}
public void testGetWithNodes() {
IPreferencesService service = Platform.getPreferencesService();
String qualifier = getUniqueString();
String key = getUniqueString();
String expected = getUniqueString();
// nothing set - navigation
Preferences node = service.getRootNode().node(TestScope.SCOPE).node(qualifier);
String actual = node.get(key, null);
assertNull("10", actual);
// nothing set - service searching
actual = service.get(key, null, new Preferences[] {node});
assertNull("2.0", actual);
// set value
node.put(key, expected);
// value is set - navigation
actual = node.get(key, null);
assertNotNull("3.0", actual);
assertEquals("3.1", expected, actual);
// value is set - service searching
actual = service.get(key, null, new Preferences[] {node});
assertNotNull("4.0", actual);
assertEquals("4.1", expected, actual);
// return default value if node list is null
actual = service.get(key, null, null);
assertNull("5.0", actual);
// skip over null nodes
actual = service.get(key, null, new Preferences[] {null, node});
assertNotNull("6.0", actual);
assertEquals("6.1", expected, actual);
// set the value in the default scope as well
Preferences defaultNode = service.getRootNode().node(DefaultScope.SCOPE).node(qualifier);
String defaultValue = getUniqueString();
defaultNode.put(key, defaultValue);
actual = defaultNode.get(key, null);
assertNotNull("7.0", actual);
assertEquals("7.1", defaultValue, actual);
// pass in both nodes
actual = service.get(key, null, new Preferences[] {node, defaultNode});
assertNotNull("8.0", actual);
assertEquals("8.1", expected, actual);
// skip nulls
actual = service.get(key, null, new Preferences[] {null, node, null, defaultNode, null});
assertNotNull("8.2", actual);
assertEquals("8.3", expected, actual);
// reverse the order
actual = service.get(key, null, new Preferences[] {defaultNode, node});
assertNotNull("8.4", actual);
assertEquals("8.5", defaultValue, actual);
// skip nulls
actual = service.get(key, null, new Preferences[] {null, null, defaultNode, null, node, null});
assertNotNull("8.6", actual);
assertEquals("8.7", defaultValue, actual);
}
public void testSearchingStringBasics() {
IPreferencesService service = Platform.getPreferencesService();
String qualifier = getUniqueString();
String key = getUniqueString();
Preferences node = service.getRootNode().node(TestScope.SCOPE).node(qualifier);
Preferences defaultNode = service.getRootNode().node(DefaultScope.SCOPE).node(qualifier);
String value = getUniqueString();
String defaultValue = getUniqueString() + '1';
String actual = null;
List<IScopeContext[]> list = new ArrayList<>();
list.add(null);
list.add(new IScopeContext[] {});
list.add(new IScopeContext[] {null});
list.add(new IScopeContext[] {new TestScope()});
list.add(new IScopeContext[] {new TestScope(), DefaultScope.INSTANCE});
list.add(new IScopeContext[] {DefaultScope.INSTANCE, new TestScope()});
list.add(new IScopeContext[] {DefaultScope.INSTANCE});
IScopeContext[][] contexts = list.toArray(new IScopeContext[list.size()][]);
// nothing is set
for (int i = 0; i < contexts.length; i++) {
actual = service.getString(qualifier, key, null, contexts[i]);
assertNull("1.0." + i, actual);
}
// set a default value
defaultNode.put(key, defaultValue);
actual = defaultNode.get(key, null);
assertNotNull("2.0", actual);
assertEquals("2.1", defaultValue, actual);
// should find it because "default" is in the default-default lookup order
for (int i = 0; i < contexts.length; i++) {
actual = service.getString(qualifier, key, null, contexts[i]);
assertNotNull("3.0." + i, actual);
assertEquals("3.1." + i, defaultValue, actual);
}
// set a real value
node.put(key, value);
actual = node.get(key, null);
assertNotNull("4.0", actual);
assertEquals("4.1", value, actual);
// should find the default value since the "test" scope isn't in the lookup order
for (int i = 0; i < contexts.length; i++) {
actual = service.getString(qualifier, key, null, contexts[i]);
assertNotNull("5.0." + i, actual);
assertEquals("5.1." + i, defaultValue, actual);
}
// set the lookup order for qualifier/null
String[] setOrder = new String[] {TestScope.SCOPE, DefaultScope.SCOPE};
service.setDefaultLookupOrder(qualifier, null, setOrder);
String[] order = service.getLookupOrder(qualifier, null);
assertNotNull("6.0", order);
assertEquals("6.1", setOrder, order);
// get the value, should be the real one
for (int i = 0; i < contexts.length; i++) {
actual = service.getString(qualifier, key, null, contexts[i]);
assertNotNull("7.0." + i, actual);
assertEquals("7.1." + i, value, actual);
}
// set the order to be the reverse for the qualifier/key
setOrder = new String[] {DefaultScope.SCOPE, TestScope.SCOPE};
service.setDefaultLookupOrder(qualifier, key, setOrder);
order = service.getLookupOrder(qualifier, key);
assertNotNull("8.0", order);
assertEquals("8.1", setOrder, order);
// get the value, should be the default one
for (int i = 0; i < contexts.length; i++) {
actual = service.getString(qualifier, key, null, contexts[i]);
assertNotNull("9.0." + i, actual);
assertEquals("9.1." + i, defaultValue, actual);
}
}
@Override
protected void tearDown() throws Exception {
super.tearDown();
Platform.getPreferencesService().getRootNode().node(TestScope.SCOPE).removeNode();
}
public void testGet() {
IPreferencesService service = Platform.getPreferencesService();
String qualifier = getUniqueString();
Preferences node = service.getRootNode().node(TestScope.SCOPE).node(qualifier);
service.setDefaultLookupOrder(qualifier, null, new String[] {TestScope.SCOPE});
// fun with paths
String searchPath = "a";
node.put("a", searchPath);
assertEquals("3.0", searchPath, service.getString(qualifier, searchPath, null, null));
searchPath = "a/b";
node.node("a").put("b", searchPath);
assertEquals("4.0", searchPath, service.getString(qualifier, searchPath, null, null));
searchPath = "a//b";
node.node("a").put("b", searchPath);
assertEquals("5.0", searchPath, service.getString(qualifier, searchPath, null, null));
searchPath = "a/b//c";
node.node("a").node("b").put("c", searchPath);
assertEquals("6.0", searchPath, service.getString(qualifier, searchPath, null, null));
searchPath = "a/b//c/d";
node.node("a").node("b").put("c/d", searchPath);
assertEquals("7.0", searchPath, service.getString(qualifier, searchPath, null, null));
searchPath = "/a";
node.put("a", searchPath);
assertEquals("8.0", searchPath, service.getString(qualifier, searchPath, null, null));
searchPath = "/a/b";
node.node("a").put("b", searchPath);
assertEquals("9.0", searchPath, service.getString(qualifier, searchPath, null, null));
searchPath = "///a";
node.put("/a", searchPath);
assertEquals("10.0", searchPath, service.getString(qualifier, searchPath, null, null));
}
public void testImportExceptions() {
// importing an empty file is an error (invalid file format)
IPreferencesService service = Platform.getPreferencesService();
InputStream input = new BufferedInputStream(new ByteArrayInputStream(new byte[0]));
try {
service.importPreferences(input);
fail("0.0");
} catch (CoreException e) {
// expected
}
}
public void testImportLegacy() {
IPreferencesService service = Platform.getPreferencesService();
String[] qualifiers = new String[] {getUniqueString() + 1, getUniqueString() + 2};
String[] oldKeys = new String[] {getUniqueString() + 3, getUniqueString() + 4};
String[] newKeys = new String[] {getUniqueString() + 5, getUniqueString() + 6};
Preferences node = service.getRootNode().node(Plugin.PLUGIN_PREFERENCE_SCOPE);
String actual;
// nodes shouldn't exist
for (String qualifier : qualifiers) {
try {
assertTrue("1.0", !node.nodeExists(qualifier));
} catch (BackingStoreException e) {
fail("1.99", e);
}
}
// store some values
for (String qualifier : qualifiers) {
Preferences current = node.node(qualifier);
for (String oldKey : oldKeys) {
current.put(oldKey, getUniqueString());
actual = current.get(oldKey, null);
assertNotNull("2.0." + current.absolutePath() + IPath.SEPARATOR + oldKey, actual);
}
for (String newKey : newKeys) {
actual = current.get(newKey, null);
assertNull("2.1." + current.absolutePath() + IPath.SEPARATOR + newKey, actual);
}
}
// import a legacy file
try {
service.importPreferences(getLegacyExportFile(qualifiers, newKeys));
} catch (CoreException e) {
fail("3.0", e);
}
// old values shouldn't exist anymore
for (String qualifier : qualifiers) {
Preferences current = node.node(qualifier);
for (String oldKey : oldKeys) {
assertNull("4.0." + current.absolutePath() + IPath.SEPARATOR + oldKey, current.get(oldKey, null));
}
for (String newKey : newKeys) {
actual = current.get(newKey, null);
assertNotNull("4.1." + current.absolutePath() + IPath.SEPARATOR + newKey, actual);
}
}
}
private InputStream getLegacyExportFile(String[] qualifiers, String[] keys) {
Properties properties = new Properties();
for (String qualifier : qualifiers) {
// version id
properties.put(qualifier, "2.1.3");
for (String key : keys) {
properties.put(qualifier + IPath.SEPARATOR + key, getUniqueString());
}
}
ByteArrayOutputStream output = new ByteArrayOutputStream();
try {
properties.store(output, null);
} catch (IOException e) {
fail("#getLegacyExportFile", e);
} finally {
try {
output.close();
} catch (IOException e) {
// ignore
}
}
return new ByteArrayInputStream(output.toByteArray());
}
/*
* - create a child node with some key/value pairs
* - set the excludes to be the child name
* - export the parent
* - don't expect anything to be exported
*/
public void testExportExcludes1() {
// add some random key/value pairs
String qualifier = getUniqueString();
String child = "child";
IEclipsePreferences node = new TestScope().getNode(qualifier);
Preferences childNode = node.node(child);
childNode.put("a", "v1");
childNode.put("b", "v2");
childNode.put("c", "v3");
// set the excludes list so it doesn't export anything
String[] excludes = new String[] {child};
ExportVerifier verifier = new ExportVerifier(node, excludes);
verifier.verify();
// make the child path absolute and try again
verifier.setExcludes(new String[] {'/' + child});
verifier.verify();
}
/*
* - basic export
* - set a key/value pair on a node
* - export that node
* - nothing in the excludes list
* - expect that k/v pair to be in the file
*/
public void testExportExcludes2() {
String qualifier = getUniqueString();
IEclipsePreferences node = new TestScope().getNode(qualifier);
String key = getUniqueString();
String value = getUniqueString();
node.put(key, value);
String[] excludesList = new String[] {};
ExportVerifier verifier = new ExportVerifier(node, excludesList);
verifier.addExpected(node.absolutePath(), key);
verifier.addVersion();
verifier.addExportRoot(node);
verifier.verify();
}
/*
* - add 2 key/value pairs to a node
* - add one of them to the excludes list
* - expect only the other key to exist
*/
public void testExportExcludes3() {
String qualifier = getUniqueString();
IEclipsePreferences node = new TestScope().getNode(qualifier);
String k1 = "a";
String k2 = "b";
String v1 = "1";
String v2 = "2";
node.put(k1, v1);
node.put(k2, v2);
String[] excludesList = new String[] {k1};
ExportVerifier verifier = new ExportVerifier(node, excludesList);
verifier.addExpected(node.absolutePath(), k2);
verifier.addVersion();
verifier.addExportRoot(node);
verifier.verify();
// make the excludes list absolute paths and try again
verifier.setExcludes(new String[] {'/' + k1});
verifier.verify();
}
/*
* - add key/value pairs to a node
* - export containing non-matching string
* - expect all k/v pairs
*/
public void testExportExcludes4() {
String qualifier = getUniqueString();
IEclipsePreferences node = new TestScope().getNode(qualifier);
String k1 = "a";
String k2 = "b";
String v1 = "1";
String v2 = "2";
node.put(k1, v1);
node.put(k2, v2);
String[] excludesList = new String[] {"bar"};
ExportVerifier verifier = new ExportVerifier(node, excludesList);
verifier.addVersion();
verifier.addExportRoot(node);
verifier.addExpected(node.absolutePath(), k1);
verifier.addExpected(node.absolutePath(), k2);
verifier.verify();
}
/**
* Tests a default preference value set by a preference initializer extension.
*/
public void testDefaultFromInitializer() {
String value = Platform.getPreferencesService().getString(RuntimeTestsPlugin.PI_RUNTIME_TESTS, TestInitializer.DEFAULT_PREF_KEY, null, null);
assertEquals("1.0", TestInitializer.DEFAULT_PREF_VALUE, value);
}
/*
* - exporting default values shouldn't do anything
*/
public void testExportDefaults() {
String qualifier = getUniqueString();
IEclipsePreferences node = DefaultScope.INSTANCE.getNode(qualifier);
for (int i = 0; i < 10; i++) {
node.put(Integer.toString(i), getUniqueString());
}
ExportVerifier verifier = new ExportVerifier(node, (String[]) null);
verifier.verify();
}
/*
* - create 2 child with 2 key/value pairs each
* - excludes is a single key from one of the children
* - export parent
* - expect all values to be exported but that one
*/
public void testExportExcludes5() {
String qualifier = getUniqueString();
IEclipsePreferences node = new TestScope().getNode(qualifier);
Preferences child1 = node.node("c1");
Preferences child2 = node.node("c2");
String k1 = "a";
String k2 = "b";
String v1 = "1";
String v2 = "2";
child1.put(k1, v1);
child1.put(k2, v2);
child2.put(k1, v1);
child2.put(k2, v2);
String[] excludes = new String[] {child1.name() + '/' + k2};
ExportVerifier verifier = new ExportVerifier(node, excludes);
verifier.addVersion();
verifier.addExportRoot(node);
verifier.addExpected(child1.absolutePath(), k1);
verifier.addExpected(child2.absolutePath(), k1);
verifier.addExpected(child2.absolutePath(), k2);
}
/**
* @deprecated this tests deprecated functions, so deprecation added to avoid warnings
*/
@Deprecated
public void testValidateVersions() {
final char BUNDLE_VERSION_PREFIX = '@';
// ensure that there is at least one value in the prefs
Preferences scopeRoot = Platform.getPreferencesService().getRootNode().node(Plugin.PLUGIN_PREFERENCE_SCOPE);
scopeRoot.node("org.eclipse.core.tests.runtime").put("key", "value");
// no errors if the file doesn't exist
IPath path = getRandomLocation();
IStatus result = org.eclipse.core.runtime.Preferences.validatePreferenceVersions(path);
assertTrue("1.0", result.isOK());
// an empty file wasn't written by #export so its an invalid file format
// NOTE: this changed from "do nothing" to being an error in Eclipse 3.1
Properties properties = new Properties();
OutputStream output = null;
try {
output = new FileOutputStream(path.toFile());
properties.store(output, null);
} catch (IOException e) {
fail("2.0", e);
} finally {
if (output != null) {
try {
output.close();
} catch (IOException e) {
// ignore
}
}
}
result = org.eclipse.core.runtime.Preferences.validatePreferenceVersions(path);
assertTrue("2.0", !result.isOK());
// no errors for a file which we write out right now
try {
org.eclipse.core.runtime.Preferences.exportPreferences(path);
} catch (CoreException e) {
fail("3.0", e);
}
result = org.eclipse.core.runtime.Preferences.validatePreferenceVersions(path);
assertTrue("3.1", result.isOK());
// warning for old versions
properties = new Properties();
InputStream input = null;
try {
input = new FileInputStream(path.toFile());
properties.load(input);
} catch (IOException e) {
fail("4.0", e);
} finally {
if (input != null) {
try {
input.close();
} catch (IOException e) {
// ignore
}
}
}
// change all version numbers to "0" so the validation will fail
for (Enumeration<Object> e = properties.keys(); e.hasMoreElements();) {
String key = (String) e.nextElement();
if (key.charAt(0) == BUNDLE_VERSION_PREFIX) {
properties.put(key, "0");
}
}
output = null;
try {
output = new FileOutputStream(path.toFile());
properties.store(output, null);
} catch (IOException e) {
fail("4.1", e);
} finally {
if (output != null) {
try {
output.close();
} catch (IOException e) {
// ignore
}
}
}
result = org.eclipse.core.runtime.Preferences.validatePreferenceVersions(path);
assertTrue("4.2", !result.isOK());
}
public void testMatches() {
IPreferencesService service = Platform.getPreferencesService();
IPreferenceFilter[] matching = null;
final String QUALIFIER = getUniqueString();
// an empty transfer list matches nothing
try {
matching = service.matches(service.getRootNode(), new IPreferenceFilter[0]);
} catch (CoreException e) {
fail("1.00", e);
}
assertEquals("1.1", 0, matching.length);
// don't match this filter
IPreferenceFilter filter = new IPreferenceFilter() {
@Override
public Map<String, PreferenceFilterEntry[]> getMapping(String scope) {
Map<String, PreferenceFilterEntry[]> result = new HashMap<>();
result.put(QUALIFIER, null);
return result;
}
@Override
public String[] getScopes() {
return new String[] {InstanceScope.SCOPE};
}
};
try {
matching = service.matches(service.getRootNode(), new IPreferenceFilter[] {filter});
} catch (CoreException e) {
fail("2.00", e);
}
assertEquals("2.1", 0, matching.length);
// shouldn't match since there are no key/value pairs in the node
try {
matching = service.matches(service.getRootNode(), new IPreferenceFilter[] {filter});
} catch (CoreException e) {
fail("3.00", e);
}
assertEquals("3.0", 0, matching.length);
// add some values so it does match
InstanceScope.INSTANCE.getNode(QUALIFIER).put("key", "value");
try {
matching = service.matches(service.getRootNode(), new IPreferenceFilter[] {filter});
} catch (CoreException e) {
fail("3.00", e);
}
assertEquals("3.1", 1, matching.length);
// should match on the exact node too
try {
matching = service.matches(InstanceScope.INSTANCE.getNode(QUALIFIER), new IPreferenceFilter[] {filter});
} catch (CoreException e) {
fail("4.00", e);
}
assertEquals("4.1", 1, matching.length);
// shouldn't match a different scope
try {
matching = service.matches(ConfigurationScope.INSTANCE.getNode(QUALIFIER), new IPreferenceFilter[] {filter});
} catch (CoreException e) {
fail("5.00", e);
}
assertEquals("5.1", 0, matching.length);
// try matching on the root node for a filter which matches all nodes in the scope
filter = new IPreferenceFilter() {
@Override
public Map<String, PreferenceFilterEntry[]> getMapping(String scope) {
return null;
}
@Override
public String[] getScopes() {
return new String[] {InstanceScope.SCOPE};
}
};
try {
matching = service.matches(InstanceScope.INSTANCE.getNode(QUALIFIER), new IPreferenceFilter[] {filter});
} catch (CoreException e) {
fail("6.0", e);
}
assertEquals("6.1", 1, matching.length);
// shouldn't match
try {
matching = service.matches(ConfigurationScope.INSTANCE.getNode(QUALIFIER), new IPreferenceFilter[] {filter});
} catch (CoreException e) {
fail("7.0", e);
}
assertEquals("7.1", 0, matching.length);
}
/*
* See bug 95608 - A node should match if it has any keys OR has a child node
* with keys.
*/
public void testMatches2() {
IPreferencesService service = Platform.getPreferencesService();
final String QUALIFIER = getUniqueString();
// setup - create a child node with a key/value pair
InstanceScope.INSTANCE.getNode(QUALIFIER).node("child").put("key", "value");
IPreferenceFilter[] filters = new IPreferenceFilter[] {new IPreferenceFilter() {
@Override
public Map<String, PreferenceFilterEntry[]> getMapping(String scope) {
Map<String, PreferenceFilterEntry[]> result = new HashMap<>();
result.put(QUALIFIER, null);
return result;
}
@Override
public String[] getScopes() {
return new String[] {InstanceScope.SCOPE};
}
}};
try {
assertEquals("1.0", 1, service.matches(service.getRootNode(), filters).length);
} catch (CoreException e) {
fail("0.0", e);
}
}
public void testExportWithTransfers1() {
final String VALID_QUALIFIER = getUniqueString();
IPreferenceFilter transfer = new IPreferenceFilter() {
@Override
public Map<String, PreferenceFilterEntry[]> getMapping(String scope) {
Map<String, PreferenceFilterEntry[]> result = new HashMap<>();
result.put(VALID_QUALIFIER, null);
return result;
}
@Override
public String[] getScopes() {
return new String[] {InstanceScope.SCOPE};
}
};
IPreferencesService service = Platform.getPreferencesService();
ExportVerifier verifier = new ExportVerifier(service.getRootNode(), new IPreferenceFilter[] {transfer});
IEclipsePreferences node = InstanceScope.INSTANCE.getNode(VALID_QUALIFIER);
String VALID_KEY_1 = "key1";
String VALID_KEY_2 = "key2";
node.put(VALID_KEY_1, "value1");
node.put(VALID_KEY_2, "value2");
verifier.addVersion();
verifier.addExportRoot(service.getRootNode());
verifier.addExpected(node.absolutePath(), VALID_KEY_1);
verifier.addExpected(node.absolutePath(), VALID_KEY_2);
node = InstanceScope.INSTANCE.getNode(getUniqueString());
node.put("invalidkey1", "value1");
node.put("invalidkey2", "value2");
verifier.verify();
}
/*
* Test exporting with a transfer that returns null for the mapping. This means
* export everything in the scope.
*/
public void testExportWithTransfers2() {
final String VALID_QUALIFIER = getUniqueString();
IPreferenceFilter transfer = new IPreferenceFilter() {
@Override
public Map<String, PreferenceFilterEntry[]> getMapping(String scope) {
return null;
}
@Override
public String[] getScopes() {
return new String[] {TestScope.SCOPE};
}
};
IPreferencesService service = Platform.getPreferencesService();
final ExportVerifier verifier = new ExportVerifier(service.getRootNode(), new IPreferenceFilter[] {transfer});
IEclipsePreferences testNode = new TestScope().getNode(VALID_QUALIFIER);
String VALID_KEY_1 = "key1";
String VALID_KEY_2 = "key2";
testNode.put(VALID_KEY_1, "value1");
testNode.put(VALID_KEY_2, "value2");
IPreferenceNodeVisitor visitor = node -> {
String[] keys = node.keys();
for (String key : keys) {
verifier.addExpected(node.absolutePath(), key);
}
return true;
};
try {
((IEclipsePreferences) service.getRootNode().node(TestScope.SCOPE)).accept(visitor);
} catch (BackingStoreException e) {
fail("2.00", e);
}
verifier.addVersion();
verifier.addExportRoot(service.getRootNode());
testNode = InstanceScope.INSTANCE.getNode(getUniqueString());
testNode.put("invalidkey1", "value1");
testNode.put("invalidkey2", "value2");
verifier.verify();
}
/*
* See Bug 95608 - [Preferences] How do I specify a nested node in a preferenceTransfer
* When you specify a transfer with children, you should export it even if the
* parent doesn't have any key/value pairs.
*/
public void testExportWithTransfers3() {
final String QUALIFIER = getUniqueString();
IPreferenceFilter transfer = new IPreferenceFilter() {
@Override
public Map<String, PreferenceFilterEntry[]> getMapping(String scope) {
Map<String, PreferenceFilterEntry[]> result = new HashMap<>();
result.put(QUALIFIER, null);
return result;
}
@Override
public String[] getScopes() {
return new String[] {InstanceScope.SCOPE};
}
};
IPreferencesService service = Platform.getPreferencesService();
ExportVerifier verifier = new ExportVerifier(service.getRootNode(), new IPreferenceFilter[] {transfer});
Preferences node = InstanceScope.INSTANCE.getNode(QUALIFIER).node("child");
String VALID_KEY_1 = "key1";
String VALID_KEY_2 = "key2";
node.put(VALID_KEY_1, "value1");
node.put(VALID_KEY_2, "value2");
verifier.addVersion();
verifier.addExportRoot(service.getRootNode());
verifier.addExpected(node.absolutePath(), VALID_KEY_1);
verifier.addExpected(node.absolutePath(), VALID_KEY_2);
node = InstanceScope.INSTANCE.getNode(getUniqueString());
node.put("invalidkey1", "value1");
node.put("invalidkey2", "value2");
verifier.verify();
}
/*
* See Bug 208564 - [Preferences] preferenceTransfer: Allow wildcards on keys
* Since 3.6 preferenceTransfer allows to define common prefix for group of
* preferences
*/
public void testExportWithTransfers4() {
final String VALID_QUALIFIER = getUniqueString();
final String COMMON_PREFIX = "PREFIX.";
IPreferenceFilter transfer = new IPreferenceFilter() {
Map<String, PreferenceFilterEntry[]> result;
@Override
public Map<String, PreferenceFilterEntry[]> getMapping(String scope) {
if (result == null) {
result = new HashMap<>();
result.put(VALID_QUALIFIER, new PreferenceFilterEntry[] {new PreferenceFilterEntry(COMMON_PREFIX, "prefix")});
}
return result;
}
@Override
public String[] getScopes() {
return new String[] {InstanceScope.SCOPE};
}
};
IPreferenceFilter[] matching = null;
IPreferencesService service = Platform.getPreferencesService();
IEclipsePreferences node = InstanceScope.INSTANCE.getNode(VALID_QUALIFIER);
String VALID_KEY_1 = COMMON_PREFIX + "key1";
String VALID_KEY_2 = COMMON_PREFIX + "key2";
String VALID_KEY_3 = "key3";
String VALID_KEY_4 = "key4";
node.put(VALID_KEY_1, "value1");
node.put(VALID_KEY_2, "value2");
node.put(VALID_KEY_3, "value3");
node.put(VALID_KEY_4, "value4");
try {
matching = service.matches(service.getRootNode(), new IPreferenceFilter[] {transfer});
} catch (CoreException e) {
fail("1.00", e);
}
assertEquals("2.00", 1, matching.length);
ExportVerifier verifier = new ExportVerifier(service.getRootNode(), new IPreferenceFilter[] {transfer});
verifier.addVersion();
verifier.addExportRoot(service.getRootNode());
verifier.addExpected(node.absolutePath(), VALID_KEY_1);
verifier.addExpected(node.absolutePath(), VALID_KEY_2);
verifier.verify();
}
/**
* The test verifies that there is no PreferenceModifyListener which modifies unknown
* exported preferences node. Unnecessary nodes must not be created because empty
* exported node means that when it is applied to global preferences hierarchy, all
* preferences from the global node with the same path as the exported node
* will be removed.
* <p>
* If the test fails, you need to fix every PreferenceModifyListener that created
* unnecessary node. Failure message gives a hint which plug-ins you need to start
* with, although it is not 100% accurate since some plug-ins migrate old-style
* preferences from other plug-ins.
* <p>
* If you need to manually verify the bug, use the steps from
* https://bugs.eclipse.org/bugs/show_bug.cgi?id=418046#c0
* <p>
* For more details see bug 418046:
* https://bugs.eclipse.org/bugs/show_bug.cgi?id=418046
*/
public void testApplyAndExportedPreferencesNotModified() throws BackingStoreException, CoreException {
// create a dummy node and export it to a stream
IEclipsePreferences toExport = InstanceScope.INSTANCE.getNode("bug418046");
toExport.put("someKey", "someValue");
IPreferencesService service = Platform.getPreferencesService();
ByteArrayOutputStream stream = new ByteArrayOutputStream();
assertTrue(service.exportPreferences(toExport, stream, null).isOK());
// read preferences from a stream
IExportedPreferences exported = service.readPreferences(new ByteArrayInputStream(stream.toByteArray()));
// verify that reading from a stream does not modify exported preferences
verifyExportedPreferencesNotModified(exported);
// use the export root node to apply it to the global preferences hierarchy;
// it does not change the behavior of the apply method, but shows more problems in
// implementations of PreferenceModifyListener
exported = (IExportedPreferences) exported.node(InstanceScope.SCOPE).node("bug418046");
// apply exported preferences to the global preferences hierarchy
assertTrue(service.applyPreferences(exported).isOK());
// verify that applying does not modify exported preferences
verifyExportedPreferencesNotModified(exported);
}
private void verifyExportedPreferencesNotModified(IExportedPreferences exported) throws BackingStoreException {
Preferences node = exported;
while (node.parent() != null) {
node = node.parent();
}
String debugString = ((EclipsePreferences) node).toDeepDebugString();
String[] children = node.childrenNames();
assertEquals(debugString, 1, children.length);
assertEquals(InstanceScope.SCOPE, children[0]);
node = node.node(children[0]);
children = node.childrenNames();
assertEquals(debugString, 1, children.length);
assertEquals("bug418046", children[0]);
node = node.node(children[0]);
children = node.childrenNames();
assertEquals(debugString, 0, children.length);
assertEquals(debugString, "someValue", node.get("someKey", null));
}
public void testApplyWithTransfers() {
// todo
}
}