/*******************************************************************************
 *  Copyright (c) 2004, 2015 IBM Corporation and others.
 *  All rights reserved. This program and the accompanying materials
 *  are made available under the terms of the Eclipse Public License v1.0
 *  which accompanies this distribution, and is available at
 *  http://www.eclipse.org/legal/epl-v10.html
 *
 *  Contributors:
 *     IBM Corporation - initial API and implementation
 *******************************************************************************/
package org.eclipse.core.tests.runtime;

import java.io.*;
import java.util.*;
import junit.framework.Test;
import junit.framework.TestSuite;
import org.eclipse.core.internal.preferences.legacy.PreferenceForwarder;
import org.eclipse.core.internal.runtime.RuntimeLog;
import org.eclipse.core.runtime.*;
import org.eclipse.core.runtime.Preferences.IPropertyChangeListener;
import org.eclipse.core.runtime.Preferences.PropertyChangeEvent;
import org.eclipse.core.runtime.preferences.IEclipsePreferences;
import org.eclipse.core.runtime.preferences.InstanceScope;
import org.osgi.service.prefs.BackingStoreException;

/**
 * Test suite for API class org.eclipse.core.runtime.Preferences
 * @deprecated This class tests intentionally tests deprecated functionality, so tag
 * added to hide deprecation reference warnings.
 */
public class PreferenceForwarderTest extends RuntimeTest {

	class Tracer implements Preferences.IPropertyChangeListener {
		public StringBuffer log = new StringBuffer();

		private String typeCode(Object value) {
			if (value == null)
				return ""; //$NON-NLS-1$
			if (value instanceof Boolean)
				return "B"; //$NON-NLS-1$
			if (value instanceof Integer)
				return "I"; //$NON-NLS-1$
			if (value instanceof Long)
				return "L"; //$NON-NLS-1$
			if (value instanceof Float)
				return "F"; //$NON-NLS-1$
			if (value instanceof Double)
				return "D"; //$NON-NLS-1$
			if (value instanceof String)
				return "S"; //$NON-NLS-1$
			assertTrue("0.0", false); //$NON-NLS-1$
			return null;
		}

		@Override
		public void propertyChange(Preferences.PropertyChangeEvent event) {
			log.append('[');
			log.append(event.getProperty());
			log.append(':');
			log.append(typeCode(event.getOldValue()));
			log.append(event.getOldValue() == null ? "null" : event.getOldValue()); //$NON-NLS-1$
			log.append("->"); //$NON-NLS-1$
			log.append(typeCode(event.getNewValue()));
			log.append(event.getNewValue() == null ? "null" : event.getNewValue()); //$NON-NLS-1$
			log.append(']');
		}
	}

	public PreferenceForwarderTest(String name) {
		super(name);
	}

	public static Test suite() {
		// all test methods are named "test..."
		return new TestSuite(PreferenceForwarderTest.class);

		//				TestSuite suite = new TestSuite();
		//				suite.addTest(new PreferenceForwarderTest("testListenerOnRemove"));
		//				return suite;
	}

	@Override
	protected void setUp() {
		// do nothing
	}

	@Override
	protected void tearDown() {
		// do nothing
	}

	public void testConstants() {
		// make sure that the preference store constants are defined properly
		assertEquals("1.0", false, Preferences.BOOLEAN_DEFAULT_DEFAULT);
		assertEquals("1.1", 0, Preferences.INT_DEFAULT_DEFAULT);
		assertEquals("1.2", 0L, Preferences.LONG_DEFAULT_DEFAULT);
		assertEquals("1.3", 0.0f, Preferences.FLOAT_DEFAULT_DEFAULT, 0.0f);
		assertEquals("1.4", 0.0, Preferences.DOUBLE_DEFAULT_DEFAULT, 0.0);
		assertEquals("1.5", "", Preferences.STRING_DEFAULT_DEFAULT);
	}

	public void testBasics() {

		Preferences ps = new PreferenceForwarder(getUniqueString());
		final String k1 = "key1";
		final String v1 = "1";
		final String v2 = "2";
		final String v3 = "3";

		// check that a random property in a newly created store
		// appearchs to have default-default values of whatever type asked for
		assertEquals("1.0", true, ps.isDefault(k1));
		assertEquals("1.1", Preferences.BOOLEAN_DEFAULT_DEFAULT, ps.getBoolean(k1));
		assertEquals("1.2", Preferences.INT_DEFAULT_DEFAULT, ps.getInt(k1));
		assertEquals("1.3", Preferences.LONG_DEFAULT_DEFAULT, ps.getLong(k1));
		assertEquals("1.4", Preferences.FLOAT_DEFAULT_DEFAULT, ps.getFloat(k1), 0.0f);
		assertEquals("1.5", Preferences.DOUBLE_DEFAULT_DEFAULT, ps.getDouble(k1), 0.0);
		assertEquals("1.6", Preferences.STRING_DEFAULT_DEFAULT, ps.getString(k1));

		assertEquals("1.7", Preferences.BOOLEAN_DEFAULT_DEFAULT, ps.getDefaultBoolean(k1));
		assertEquals("1.8", Preferences.INT_DEFAULT_DEFAULT, ps.getDefaultInt(k1));
		assertEquals("1.9", Preferences.LONG_DEFAULT_DEFAULT, ps.getDefaultLong(k1));
		assertEquals("1.10", Preferences.FLOAT_DEFAULT_DEFAULT, ps.getDefaultFloat(k1), 0.0f);
		assertEquals("1.11", Preferences.DOUBLE_DEFAULT_DEFAULT, ps.getDefaultDouble(k1), 0.0);
		assertEquals("1.12", Preferences.STRING_DEFAULT_DEFAULT, ps.getDefaultString(k1));

		// test set/getString
		// give it a value
		ps.setValue(k1, v1);
		assertTrue("2.0", ps.isDefault(k1) == false);
		assertEquals("2.1", v1, ps.getString(k1));
		assertEquals("2.2", Preferences.STRING_DEFAULT_DEFAULT, ps.getDefaultString(k1));
		// change the value
		ps.setValue(k1, v2);
		assertTrue("2.3", ps.isDefault(k1) == false);
		assertEquals("2.4", v2, ps.getString(k1));
		assertEquals("2.5", Preferences.STRING_DEFAULT_DEFAULT, ps.getDefaultString(k1));
		// change to same value as default
		ps.setValue(k1, ps.getDefaultString(k1));
		assertTrue("2.6", ps.isDefault(k1) == true);
		assertEquals("2.7", ps.getDefaultString(k1), ps.getString(k1));
		assertEquals("2.8", Preferences.STRING_DEFAULT_DEFAULT, ps.getDefaultString(k1));
		// reset to default
		ps.setValue(k1, v2);
		ps.setToDefault(k1);
		assertTrue("2.9", ps.isDefault(k1) == true);
		assertEquals("2.10", Preferences.STRING_DEFAULT_DEFAULT, ps.getString(k1));
		assertEquals("2.11", Preferences.STRING_DEFAULT_DEFAULT, ps.getDefaultString(k1));
		// change default
		ps.setDefault(k1, v1);
		assertTrue("2.12", ps.isDefault(k1) == true);
		assertEquals("2.13", v1, ps.getString(k1));
		assertEquals("2.14", v1, ps.getDefaultString(k1));
		// set the value
		ps.setValue(k1, v2);
		assertTrue("2.15", ps.isDefault(k1) == false);
		assertEquals("2.16", v2, ps.getString(k1));
		assertEquals("2.17", v1, ps.getDefaultString(k1));
		// change to same value as default
		ps.setValue(k1, ps.getDefaultString(k1));
		assertTrue("2.18", ps.isDefault(k1) == true);
		assertEquals("2.19", ps.getDefaultString(k1), ps.getString(k1));
		assertEquals("2.20", v1, ps.getDefaultString(k1));
		// reset to default
		ps.setValue(k1, v2);
		ps.setToDefault(k1);
		assertTrue("2.21", ps.isDefault(k1) == true);
		assertEquals("2.22", v1, ps.getString(k1));
		assertEquals("2.23", v1, ps.getDefaultString(k1));
		// change default
		ps.setDefault(k1, v3);
		assertTrue("2.24", ps.isDefault(k1) == true);
		assertEquals("2.25", v3, ps.getString(k1));
		assertEquals("2.26", v3, ps.getDefaultString(k1));

	}

	public void testBoolean() {

		Preferences ps = new PreferenceForwarder(getUniqueString());
		final String k1 = "key1";

		assertEquals("1.0", false, Preferences.BOOLEAN_DEFAULT_DEFAULT);
		assertEquals("1.1", Preferences.BOOLEAN_DEFAULT_DEFAULT, ps.getBoolean(k1));

		ps.setValue(k1, true);
		assertEquals("1.2", true, ps.getBoolean(k1));
		ps.setValue(k1, false);
		assertEquals("1.3", false, ps.getBoolean(k1));

		ps.setDefault(k1, true);
		assertEquals("1.4", true, ps.getDefaultBoolean(k1));
		ps.setDefault(k1, false);
		assertEquals("1.5", false, ps.getDefaultBoolean(k1));

	}

	public void testInteger() {

		Preferences ps = new PreferenceForwarder(getUniqueString());
		final String k1 = "key1";
		final int[] values = {0, 1002, -201788, Integer.MAX_VALUE, Integer.MIN_VALUE};

		assertEquals("1.0", 0, Preferences.INT_DEFAULT_DEFAULT);
		assertEquals("1.1", Preferences.INT_DEFAULT_DEFAULT, ps.getInt(k1));

		for (int i = 0; i < values.length; i++) {
			int v1 = values[i];
			int v2 = v1 + 1;
			ps.setValue(k1, v1);
			assertEquals("1.2", v1, ps.getInt(k1));
			ps.setDefault(k1, v2);
			assertEquals("1.3", v2, ps.getDefaultInt(k1));
		}
	}

	public void testLong() {

		Preferences ps = new PreferenceForwarder(getUniqueString());
		final String k1 = "key1";
		final long[] values = {0L, 1002L, -201788L, Long.MAX_VALUE, Long.MIN_VALUE};

		assertEquals("1.0", 0L, Preferences.LONG_DEFAULT_DEFAULT);
		assertEquals("1.1", Preferences.LONG_DEFAULT_DEFAULT, ps.getLong(k1));

		for (int i = 0; i < values.length; i++) {
			long v1 = values[i];
			long v2 = v1 + 1;
			ps.setValue(k1, v1);
			assertEquals("1.2", v1, ps.getLong(k1));
			ps.setDefault(k1, v2);
			assertEquals("1.3", v2, ps.getDefaultLong(k1));
		}
	}

	public void testFloat() {

		Preferences ps = new PreferenceForwarder(getUniqueString());
		final String k1 = "key1";
		final float[] values = {0.0f, 1002.5f, -201788.55f, Float.MAX_VALUE, Float.MIN_VALUE};
		final float tol = 1.0e-20f;

		assertEquals("1.0", 0.0f, Preferences.FLOAT_DEFAULT_DEFAULT, tol);
		assertEquals("1.1", Preferences.FLOAT_DEFAULT_DEFAULT, ps.getFloat(k1), tol);

		for (int i = 0; i < values.length; i++) {
			float v1 = values[i];
			float v2 = v1 + 1.0f;
			ps.setValue(k1, v1);
			assertEquals("1.2", v1, ps.getFloat(k1), tol);
			ps.setDefault(k1, v2);
			assertEquals("1.3", v2, ps.getDefaultFloat(k1), tol);
		}

		try {
			ps.setValue(k1, Float.NaN);
			assertTrue("1.4", false);
		} catch (IllegalArgumentException e) {
			// NaNs should be rejected
		}

	}

	public void testDouble() {

		Preferences ps = new PreferenceForwarder(getUniqueString());
		final String k1 = "key1";
		final double[] values = {0.0, 1002.5, -201788.55, Double.MAX_VALUE, Double.MIN_VALUE};
		final double tol = 1.0e-20;

		assertEquals("1.0", 0.0, Preferences.DOUBLE_DEFAULT_DEFAULT, tol);
		assertEquals("1.1", Preferences.DOUBLE_DEFAULT_DEFAULT, ps.getDouble(k1), tol);

		for (int i = 0; i < values.length; i++) {
			double v1 = values[i];
			double v2 = v1 + 1.0;
			ps.setValue(k1, v1);
			assertEquals("1.2", v1, ps.getDouble(k1), tol);
			ps.setDefault(k1, v2);
			assertEquals("1.3", v2, ps.getDefaultDouble(k1), tol);
		}

		try {
			ps.setValue(k1, Float.NaN);
			assertTrue("1.4", false);
		} catch (IllegalArgumentException e) {
			// NaNs should be rejected
		}

	}

	public void testString() {

		Preferences ps = new PreferenceForwarder(getUniqueString());
		final String k1 = "key1";
		final String[] values = {"", "hello", " x ", "\n"};

		assertEquals("1.0", "", Preferences.STRING_DEFAULT_DEFAULT);
		assertEquals("1.1", ps.getString(k1), Preferences.STRING_DEFAULT_DEFAULT);

		for (int i = 0; i < values.length; i++) {
			String v1 = values[i];
			String v2 = v1 + "x";
			ps.setValue(k1, v1);
			assertEquals("1.2", v1, ps.getString(k1));
			ps.setDefault(k1, v2);
			assertEquals("1.3", v2, ps.getDefaultString(k1));
		}
	}

	public void testPropertyNames() {

		Preferences ps = new PreferenceForwarder(getUniqueString());

		// there are no properties initially
		assertEquals("1.0", 0, ps.propertyNames().length);

		String[] keys = {"a", "b", "c", "d"};

		// setting defaults does not add name to set
		for (int i = 0; i < keys.length; i++) {
			ps.setDefault(keys[i], "default");
		}
		assertEquals("1.1", 0, ps.propertyNames().length);

		// setting real values does add name to set
		for (int i = 0; i < keys.length; i++) {
			ps.setValue(keys[i], "actual");
		}
		assertEquals("1.2", keys.length, ps.propertyNames().length);

		Set<String> s1 = new HashSet<String>(Arrays.asList(keys));
		Set<String> s2 = new HashSet<String>(Arrays.asList(ps.propertyNames()));
		assertEquals("1.3", s1, s2);

		// setting to default does remove name from set
		for (int i = 0; i < keys.length; i++) {
			ps.setToDefault(keys[i]);
			Set<String> s = new HashSet<String>(Arrays.asList(ps.propertyNames()));
			assertTrue("1.4", !s.contains(keys[i]));
		}
		assertEquals("1.5", 0, ps.propertyNames().length);
	}

	public void testContains() {

		Preferences ps = new PreferenceForwarder(getUniqueString());

		// there are no properties initially
		assertEquals("1.0", false, ps.contains("a"));

		// setting defaults adds name
		ps.setDefault("a", "default");
		assertEquals("1.1", true, ps.contains("a"));

		// setting value adds name
		assertEquals("1.2", false, ps.contains("b"));
		ps.setValue("b", "any");
		assertEquals("1.3", true, ps.contains("b"));

		// setting value does not remove entry already there
		ps.setValue("a", "any");
		assertEquals("1.4", true, ps.contains("a"));
		assertEquals("1.5", true, ps.contains("b"));

		// setting to default removes name from set unless there is a default too
		ps.setToDefault("b");
		assertEquals("1.6", false, ps.contains("b"));
		ps.setToDefault("a");
		assertEquals("1.7", true, ps.contains("a"));

		// test bug 62586
		// fail gracefully in PreferenceForwarder.contains(null)
		try {
			assertTrue("2.0", !ps.contains(null));
		} catch (NullPointerException e) {
			fail("2.1", e);
		}
	}

	public void testDefaultPropertyNames() {

		Preferences ps = new PreferenceForwarder(getUniqueString());

		// there are no default properties initially
		assertEquals("1.0", 0, ps.defaultPropertyNames().length);

		String[] keys = {"a", "b", "c", "d"};

		// setting actual values does not add name to set
		for (int i = 0; i < keys.length; i++) {
			ps.setValue(keys[i], "actual");
		}
		assertEquals("1.1", 0, ps.defaultPropertyNames().length);

		// setting defaults does add name to set
		for (int i = 0; i < keys.length; i++) {
			ps.setDefault(keys[i], "default");
		}
		assertEquals("1.2", keys.length, ps.defaultPropertyNames().length);

		Set<String> s1 = new HashSet<String>(Arrays.asList(keys));
		Set<String> s2 = new HashSet<String>(Arrays.asList(ps.defaultPropertyNames()));
		assertEquals("1.3", s1, s2);

		// setting to default does not remove name from set
		for (int i = 0; i < keys.length; i++) {
			ps.setToDefault(keys[i]);
			Set<String> s = new HashSet<String>(Arrays.asList(ps.defaultPropertyNames()));
			assertTrue("1.4", s.contains(keys[i]));
		}
		assertEquals("1.5", keys.length, ps.defaultPropertyNames().length);

		// setting to default-default does not remove name from set either
		for (int i = 0; i < keys.length; i++) {
			ps.setDefault(keys[i], Preferences.STRING_DEFAULT_DEFAULT);
			Set<String> s = new HashSet<String>(Arrays.asList(ps.defaultPropertyNames()));
			assertTrue("1.6.1", s.contains(keys[i]));

			ps.setDefault(keys[i], Preferences.BOOLEAN_DEFAULT_DEFAULT);
			s = new HashSet<String>(Arrays.asList(ps.defaultPropertyNames()));
			assertTrue("1.6.2", s.contains(keys[i]));

			ps.setDefault(keys[i], Preferences.INT_DEFAULT_DEFAULT);
			s = new HashSet<String>(Arrays.asList(ps.defaultPropertyNames()));
			assertTrue("1.6.3", s.contains(keys[i]));

			ps.setDefault(keys[i], Preferences.LONG_DEFAULT_DEFAULT);
			s = new HashSet<String>(Arrays.asList(ps.defaultPropertyNames()));
			assertTrue("1.6.4", s.contains(keys[i]));

			ps.setDefault(keys[i], Preferences.FLOAT_DEFAULT_DEFAULT);
			s = new HashSet<String>(Arrays.asList(ps.defaultPropertyNames()));
			assertTrue("1.6.5", s.contains(keys[i]));

			ps.setDefault(keys[i], Preferences.DOUBLE_DEFAULT_DEFAULT);
			s = new HashSet<String>(Arrays.asList(ps.defaultPropertyNames()));
			assertTrue("1.6.6", s.contains(keys[i]));
		}
		assertEquals("1.7", keys.length, ps.defaultPropertyNames().length);
	}

	public void test55138() {
		final Preferences ps = new PreferenceForwarder(getUniqueString());

		final Tracer tracer1 = new Tracer();
		String key = "foo";

		// register one listener
		ps.addPropertyChangeListener(tracer1);
		assertEquals("1.0", "", tracer1.log.toString());

		// boolean value
		boolean booleanDefault = true;
		boolean booleanValue = false;
		ps.setDefault(key, booleanDefault);
		assertEquals("2.0", "", tracer1.log.toString());

		tracer1.log.setLength(0);
		ps.setValue(key, booleanValue);
		assertEquals("2.1", "[foo:Btrue->Bfalse]", tracer1.log.toString());

		ps.setValue(key, booleanDefault);
		assertEquals("2.2", "[foo:Btrue->Bfalse][foo:Bfalse->Btrue]", tracer1.log.toString());

		// int value
		int intDefault = 10;
		int intValue = 11;
		tracer1.log.setLength(0);
		ps.setDefault(key, intDefault);
		assertEquals("3.0", "", tracer1.log.toString());

		ps.setValue(key, intValue);
		assertEquals("3.1", "[foo:I10->I11]", tracer1.log.toString());

		ps.setValue(key, intDefault);
		assertEquals("3.2", "[foo:I10->I11][foo:I11->I10]", tracer1.log.toString());

		// double value
		double doubleDefault = 10.0;
		double doubleValue = 11.0;
		tracer1.log.setLength(0);
		ps.setDefault(key, doubleDefault);
		assertEquals("4.0", "", tracer1.log.toString());

		tracer1.log.setLength(0);
		ps.setValue(key, doubleValue);
		assertEquals("4.1", "[foo:D10.0->D11.0]", tracer1.log.toString());

		ps.setValue(key, doubleDefault);
		assertEquals("4.2", "[foo:D10.0->D11.0][foo:D11.0->D10.0]", tracer1.log.toString());

		// float value
		float floatDefault = 10.0f;
		float floatValue = 11.0f;
		tracer1.log.setLength(0);
		ps.setDefault(key, floatDefault);
		assertEquals("5.0", "", tracer1.log.toString());

		tracer1.log.setLength(0);
		ps.setValue(key, floatValue);
		assertEquals("5.1", "[foo:F10.0->F11.0]", tracer1.log.toString());

		ps.setValue(key, floatDefault);
		assertEquals("5.2", "[foo:F10.0->F11.0][foo:F11.0->F10.0]", tracer1.log.toString());

		// long value
		long longDefault = 10L;
		long longValue = 11L;
		tracer1.log.setLength(0);
		ps.setDefault(key, longDefault);
		assertEquals("6.0", "", tracer1.log.toString());

		tracer1.log.setLength(0);
		ps.setValue(key, longValue);
		assertEquals("6.1", "[foo:L10->L11]", tracer1.log.toString());

		ps.setValue(key, longDefault);
		assertEquals("6.2", "[foo:L10->L11][foo:L11->L10]", tracer1.log.toString());
	}

	public void testListeners() {

		final Preferences ps = new PreferenceForwarder(getUniqueString());

		final Tracer tracer1 = new Tracer();
		final Tracer tracer2 = new Tracer();

		// register one listener
		ps.addPropertyChangeListener(tracer1);
		assertEquals("1.0", "", tracer1.log.toString());

		// make sure it is notified in a type appropriate manner
		ps.setValue("a", "1");
		assertEquals("1.0.1", "[a:S->S1]", tracer1.log.toString());

		ps.setToDefault("a");
		tracer1.log.setLength(0);
		ps.setValue("a", true);
		assertEquals("1.0.2", "[a:Bfalse->Btrue]", tracer1.log.toString());

		ps.setToDefault("a");
		tracer1.log.setLength(0);
		ps.setValue("a", 100);
		assertEquals("1.0.3", "[a:I0->I100]", tracer1.log.toString());

		ps.setToDefault("a");
		tracer1.log.setLength(0);
		ps.setValue("a", 100L);
		assertEquals("1.0.4", "[a:L0->L100]", tracer1.log.toString());

		ps.setToDefault("a");
		tracer1.log.setLength(0);
		ps.setValue("a", 2.0f);
		assertEquals("1.0.5", "[a:F0.0->F2.0]", tracer1.log.toString());

		ps.setToDefault("a");
		tracer1.log.setLength(0);
		ps.setValue("a", 2.0);
		assertEquals("1.0.6", "[a:D0.0->D2.0]", tracer1.log.toString());

		// make sure it is notified of a series of events
		ps.setToDefault("a");
		tracer1.log.setLength(0);
		ps.setValue("a", "1");
		assertEquals("1.1", "[a:S->S1]", tracer1.log.toString());

		ps.setValue("a", "2");
		assertEquals("1.2", "[a:S->S1][a:S1->S2]", tracer1.log.toString());

		ps.setValue("a", ps.getDefaultString("a"));
		assertEquals("1.2.1", "[a:S->S1][a:S1->S2][a:S2->S]", tracer1.log.toString());

		ps.setValue("a", "3");
		assertEquals("1.2.2", "[a:S->S1][a:S1->S2][a:S2->S][a:S->S3]", tracer1.log.toString());

		ps.setToDefault("a");
		assertEquals("1.2.3", "[a:S->S1][a:S1->S2][a:S2->S][a:S->S3][a:S3->S]", tracer1.log.toString());

		// change to same value - no one notified
		ps.setValue("a", "2");
		tracer1.log.setLength(0);
		assertEquals("1.3", "", tracer1.log.toString());

		// register second listener
		ps.addPropertyChangeListener(tracer2);

		// make sure both are notified
		ps.setValue("a", "3");
		assertEquals("1.4", "[a:S2->S3]", tracer1.log.toString());
		assertEquals("1.5", "[a:S2->S3]", tracer2.log.toString());

		// deregister is honored
		ps.removePropertyChangeListener(tracer2);
		tracer1.log.setLength(0);
		tracer2.log.setLength(0);
		ps.setValue("a", "1");
		assertEquals("1.6", "[a:S3->S1]", tracer1.log.toString());
		assertEquals("1.7", "", tracer2.log.toString());

		// duplicate deregister is ignored
		ps.removePropertyChangeListener(tracer2);
		tracer1.log.setLength(0);
		tracer2.log.setLength(0);
		ps.setValue("a", "2");
		assertEquals("1.8", "[a:S1->S2]", tracer1.log.toString());
		assertEquals("1.9", "", tracer2.log.toString());

		// duplicate register is ignored
		ps.addPropertyChangeListener(tracer1);
		tracer1.log.setLength(0);
		ps.setValue("a", "1");
		assertEquals("1.10", "[a:S2->S1]", tracer1.log.toString());

		// last deregister is honored
		ps.removePropertyChangeListener(tracer1);
		tracer1.log.setLength(0);
		ps.setValue("a", "4");
		assertEquals("1.11", "", tracer1.log.toString());

		// adds 2 and removes 1 during during callback!
		class Trouble implements Preferences.IPropertyChangeListener {
			@Override
			public void propertyChange(Preferences.PropertyChangeEvent event) {
				ps.removePropertyChangeListener(tracer1);
				ps.addPropertyChangeListener(tracer2);
			}
		}

		ps.setValue("a", "0");
		ps.addPropertyChangeListener(tracer1);
		ps.addPropertyChangeListener(new Trouble());
		tracer1.log.setLength(0);
		tracer2.log.setLength(0);
		ps.setValue("a", "1");
		ps.setValue("a", "2");
		assertEquals("1.12", "[a:S0->S1]", tracer1.log.toString());
		assertEquals("1.13", "[a:S1->S2]", tracer2.log.toString());

	}

	public void testLoadStore() {

		final Preferences ps = new PreferenceForwarder(getUniqueString());

		ps.setValue("b1", true);
		ps.setValue("i1", 1);
		ps.setValue("l1", 2L);
		ps.setValue("f1", 1.0f);
		ps.setValue("d1", 1.0);
		ps.setValue("s1", "x");
		String[] keys = {"b1", "i1", "l1", "f1", "d1", "s1",};

		ByteArrayOutputStream out = new ByteArrayOutputStream();
		try {
			ps.store(out, "test header");
		} catch (IOException e) {
			assertTrue("0.1", false);
		}

		ByteArrayInputStream in = new ByteArrayInputStream(out.toByteArray());

		final Preferences ps2 = new PreferenceForwarder(getUniqueString());
		try {
			ps2.load(in);
		} catch (IOException e) {
			assertTrue("0.2", false);
		}

		assertEquals("1.1", true, ps2.getBoolean("b1"));
		assertEquals("1.2", 1, ps2.getInt("i1"));
		assertEquals("1.3", 2L, ps2.getLong("l1"));
		assertEquals("1.4", 1.0f, ps2.getFloat("f1"), 1e-20f);
		assertEquals("1.5", 1.0, ps2.getDouble("d1"), 1e-20);
		assertEquals("1.6", "x", ps2.getString("s1"));

		Set<String> s1 = new HashSet<String>(Arrays.asList(keys));
		Set<String> s2 = new HashSet<String>(Arrays.asList(ps2.propertyNames()));
		assertEquals("1.7", s1, s2);

		// load discards current values
		in = new ByteArrayInputStream(out.toByteArray());
		final Preferences ps3 = new PreferenceForwarder(getUniqueString());
		ps3.setValue("s1", "y");
		try {
			ps3.load(in);
			assertEquals("1.8", "x", ps3.getString("s1"));
			Set<String> k1 = new HashSet<String>(Arrays.asList(keys));
			Set<String> k2 = new HashSet<String>(Arrays.asList(ps3.propertyNames()));
			assertEquals("1.9", k1, k2);
		} catch (IOException e) {
			assertTrue("1.10", false);
		}

	}

	public void testNeedsSaving() {

		Preferences ps = new PreferenceForwarder(getUniqueString());

		// setValue dirties
		ps = new PreferenceForwarder(getUniqueString());
		assertEquals("1.0", false, ps.needsSaving());
		ps.setValue("b1", true);
		assertEquals("1.1", true, ps.needsSaving());

		ps = new PreferenceForwarder(getUniqueString());
		assertEquals("2.0", false, ps.needsSaving());
		ps.setValue("i1", 1);
		assertEquals("2.1", true, ps.needsSaving());

		ps = new PreferenceForwarder(getUniqueString());
		assertEquals("3.0", false, ps.needsSaving());
		ps.setValue("l1", 2L);
		assertEquals("3.1", true, ps.needsSaving());

		ps = new PreferenceForwarder(getUniqueString());
		assertEquals("4.0", false, ps.needsSaving());
		ps.setValue("f1", 1.0f);
		assertEquals("4.1", true, ps.needsSaving());

		ps = new PreferenceForwarder(getUniqueString());
		assertEquals("5.0", false, ps.needsSaving());
		ps.setValue("d1", 1.0);
		assertEquals("5.1", true, ps.needsSaving());

		ps = new PreferenceForwarder(getUniqueString());
		assertEquals("6.0", false, ps.needsSaving());
		ps.setValue("s1", "x");
		assertEquals("6.1", true, ps.needsSaving());

		// setToDefault does not dirty if value not set
		ps = new PreferenceForwarder(getUniqueString());
		assertEquals("7.0", false, ps.needsSaving());
		ps.setToDefault("any");
		assertEquals("7.1", false, ps.needsSaving());

		// setToDefault dirties if value was set
		try {
			ps = new PreferenceForwarder(getUniqueString());
			assertEquals("7.2", false, ps.needsSaving());
			ps.setValue("any", "x");
			ByteArrayOutputStream out = new ByteArrayOutputStream();
			ps.store(out, "test header");
			ByteArrayInputStream in = new ByteArrayInputStream(out.toByteArray());
			ps.load(in);
			assertEquals("7.3", false, ps.needsSaving());
			ps.setToDefault("any");
			assertEquals("7.4", true, ps.needsSaving());
		} catch (IOException e) {
			assertTrue("7.5", false);
		}

		// setDefault, getT, getDefaultT do not dirty
		ps = new PreferenceForwarder(getUniqueString());
		assertEquals("8.0", false, ps.needsSaving());
		ps.setDefault("b1", true);
		ps.getBoolean("b1");
		ps.getDefaultBoolean("b1");
		ps.setDefault("i1", 1);
		ps.getInt("i1");
		ps.getDefaultInt("i1");
		ps.setDefault("l1", 1L);
		ps.getLong("l1");
		ps.getDefaultLong("l1");
		ps.setDefault("f1", 1.0f);
		ps.getFloat("f1");
		ps.getDefaultFloat("f1");
		ps.setDefault("d1", 1.0);
		ps.getDouble("d1");
		ps.getDefaultDouble("d1");
		ps.setDefault("s1", "x");
		ps.getString("s1");
		ps.getDefaultString("s1");
		assertEquals("8.1", false, ps.needsSaving());

		try {
			ps = new PreferenceForwarder(getUniqueString());
			assertEquals("9.1", false, ps.needsSaving());
			ps.setValue("b1", true);
			assertEquals("9.2", true, ps.needsSaving());
			ByteArrayOutputStream out = new ByteArrayOutputStream();

			// store makes not dirty
			ps.store(out, "test header");
			assertEquals("9.3", false, ps.needsSaving());

			// load comes in not dirty
			ps.setValue("b1", false);
			assertEquals("9.4", true, ps.needsSaving());
			ByteArrayInputStream in = new ByteArrayInputStream(out.toByteArray());
			ps.load(in);
			assertEquals("9.5", false, ps.needsSaving());
		} catch (IOException e) {
			assertTrue("9.0", false);
		}
	}

	/* Comment this test out until we are able to use session tests
	 * with it. - ddw
	 * 	public void testPluginPrefs() {
	 IPluginRegistry registry = InternalPlatform.getPluginRegistry();
	 IPluginDescriptor resPlugin = registry.getPluginDescriptor("org.eclipse.core.resources");
	 Preferences perfs = null;
	 try {
	 perfs = resPlugin.getPlugin().getPluginPreferences();
	 } catch (CoreException ce) {
	 fail("0.1 core exception from getPlugin");
	 }
	 boolean oneBoolean = perfs.getBoolean("OneBoolean");
	 double oneDouble = perfs.getDouble("OneDouble");
	 float oneFloat = perfs.getFloat("OneFloat");
	 int oneInt = perfs.getInt("OneInt");
	 long oneLong = perfs.getLong("OneLong");
	 String oneString = perfs.getString("OneString");
	 assertTrue("1.0 boolean", oneBoolean);
	 assertTrue("2.0 double", oneDouble == 4);
	 assertTrue("3.0 float", oneFloat ==	4.3f);
	 assertTrue("4.0 int", oneInt == 5);
	 assertTrue("5.0 long", oneLong == 6);
	 assertTrue("6.0 string", oneString.equals("A string from the plugin root directory"));
	 int a = 4;
	 int b = 3;
	 }
	 */

	/*
	 * Regression test for bug 178815.
	 */
	public void testListenerOnRemove() {
		// create a new log listener that will fail if anything is written
		ILogListener logListener = new ILogListener() {
			@Override
			public void logging(IStatus status, String plugin) {
				CoreException ex = new CoreException(status);
				fail("0.99", ex);
			}
		};

		// set a preference value to get everything initialized
		String id = getUniqueString();
		Preferences ps = new PreferenceForwarder(id);
		ps.setValue("key", "value");

		// add a property change listener which will cause one to be
		// added at the preference node level
		IPropertyChangeListener listener = new Preferences.IPropertyChangeListener() {
			@Override
			public void propertyChange(PropertyChangeEvent event) {
			}
		};
		ps.addPropertyChangeListener(listener);
		ps.setValue("key2", "value2");
		IEclipsePreferences node = InstanceScope.INSTANCE.getNode(id);

		// add our log listener and remove the node. nothing should be logged.
		RuntimeLog.addLogListener(logListener);
		try {
			node.removeNode();
		} catch (BackingStoreException e) {
			fail("4.99", e);
		} catch (IllegalStateException e) {
			fail("5.00", e);
		} finally {
			RuntimeLog.removeLogListener(logListener);
		}
	}
}
