/*******************************************************************************
 * Copyright (c) 2000, 2017 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
 *     Alexander Kurtakov <akurtako@redhat.com> - Bug 459343
 *******************************************************************************/
package org.eclipse.core.tests.internal.properties;

import java.util.Vector;
import junit.framework.Test;
import junit.framework.TestSuite;
import org.eclipse.core.internal.properties.IPropertyManager;
import org.eclipse.core.internal.properties.PropertyManager2;
import org.eclipse.core.internal.resources.Workspace;
import org.eclipse.core.resources.*;
import org.eclipse.core.runtime.*;
import org.eclipse.core.tests.internal.localstore.LocalStoreTest;

public class PropertyManagerTest extends LocalStoreTest {

	public class StoredProperty {
		protected QualifiedName name = null;
		protected String value = null;

		public StoredProperty(QualifiedName name, String value) {
			super();
			this.name = name;
			this.value = value;
		}

		public QualifiedName getName() {
			return name;
		}

		public String getStringValue() {
			return value;
		}
	}

	public static Test suite() {
		//			TestSuite suite = new TestSuite();
		//			suite.addTest(new PropertyManagerTest("testDeleteProperties"));
		//			return suite;
		return new TestSuite(PropertyManagerTest.class);
	}

	public PropertyManagerTest() {
		super(null);
	}

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

	private void createProperties(IFile target, QualifiedName[] names, String[] values) {
		for (int i = 0; i < names.length; i++) {
			names[i] = new QualifiedName("org.eclipse.core.tests", "prop" + i);
			values[i] = "property value" + i;
		}
		// create properties
		for (int i = 0; i < names.length; i++) {
			try {
				target.setPersistentProperty(names[i], values[i]);
			} catch (CoreException e) {
				fail("1." + i, e);
			}
		}
	}

	private Thread[] createThreads(final IFile target, final QualifiedName[] names, final String[] values, final CoreException[] errorPointer) {
		final int THREAD_COUNT = 3;
		Thread[] threads = new Thread[THREAD_COUNT];
		for (int j = 0; j < THREAD_COUNT; j++) {
			final String id = "GetSetProperty" + j;
			threads[j] = new Thread((Runnable) () -> {
				try {
					doGetSetProperties(target, id, names, values);
				} catch (CoreException e) {
					//ignore failure if the project has been deleted
					if (target.exists()) {
						e.printStackTrace();
						errorPointer[0] = e;
						return;
					}
				}
			}, id);
			threads[j].start();
		}
		return threads;
	}

	protected void doGetSetProperties(IFile target, String threadID, QualifiedName[] names, String[] values) throws CoreException {
		final int N = names.length;
		for (int j = 0; j < 10; j++) {
			for (int i = 0; i < N; i++) {
				target.getPersistentProperty(names[i]);
			}
			// change properties
			for (int i = 0; i < N; i++) {
				//			values[i] = values[i] + " - changed (" + threadID + ")";
				target.setPersistentProperty(names[i], values[i]);
			}
			// verify
			for (int i = 0; i < N; i++) {
				target.getPersistentProperty(names[i]);
			}
		}
	}

	private void join(Thread[] threads) {
		//wait for all threads to finish
		for (Thread thread : threads) {
			try {
				thread.join();
			} catch (InterruptedException e) {
				fail("#join", e);
			}
		}
	}

	/**
	 * Tests concurrent acces to the property store.
	 */
	public void testConcurrentAccess() {

		// create common objects
		final IFile target = projects[0].getFile("target");
		try {
			target.create(getRandomContents(), true, getMonitor());
		} catch (CoreException e) {
			fail("0.0", e);
		}

		// prepare keys and values
		final int N = 50;
		final QualifiedName[] names = new QualifiedName[N];
		final String[] values = new String[N];
		createProperties(target, names, values);

		final CoreException[] errorPointer = new CoreException[1];
		Thread[] threads = createThreads(target, names, values, errorPointer);
		join(threads);
		if (errorPointer[0] != null) {
			fail("2.0", errorPointer[0]);
		}

		// remove trash
		try {
			target.delete(true, getMonitor());
		} catch (CoreException e) {
			fail("20.0", e);
		}
	}

	/**
	 * Tests concurrent access to the property store while the project is being
	 * deleted.
	 */
	public void testConcurrentDelete() {
		Thread[] threads;
		final IFile target = projects[0].getFile("target");
		final int REPEAT = 8;
		for (int i = 0; i < REPEAT; i++) {
			// create common objects
			ensureExistsInWorkspace(projects[0], true);
			ensureExistsInWorkspace(target, true);

			// prepare keys and values
			final int N = 50;
			final QualifiedName[] names = new QualifiedName[N];
			final String[] values = new String[N];
			createProperties(target, names, values);

			final CoreException[] errorPointer = new CoreException[1];
			threads = createThreads(target, names, values, errorPointer);
			try {
				//give the threads a chance to start
				Thread.sleep(10);
			} catch (InterruptedException e) {
				fail("1.98", e);
			}
			try {
				//delete the project while the threads are still running
				target.getProject().delete(IResource.NONE, getMonitor());
			} catch (CoreException e) {
				fail("1.99." + i, e);
			}
			join(threads);
			if (errorPointer[0] != null) {
				fail("2.0." + i, errorPointer[0]);
			}
		}
		// remove trash
		try {
			target.delete(true, getMonitor());
		} catch (CoreException e) {
			fail("20.0", e);
		}
	}

	public void testCopy() throws Throwable {
		IPropertyManager manager = new PropertyManager2((Workspace) ResourcesPlugin.getWorkspace());
		IProject source = projects[0];
		IFolder sourceFolder = source.getFolder("myfolder");
		IResource sourceFile = sourceFolder.getFile("myfile.txt");
		IProject destination = projects[1];
		IFolder destFolder = destination.getFolder(sourceFolder.getName());
		IResource destFile = destFolder.getFile(sourceFile.getName());
		QualifiedName propName = new QualifiedName("test", "prop");
		String propValue = "this is the property value";

		ensureExistsInWorkspace(new IResource[] {source, sourceFolder, sourceFile}, true);

		/*
		 * persistent properties
		 */
		manager.setProperty(source, propName, propValue);
		manager.setProperty(sourceFolder, propName, propValue);
		manager.setProperty(sourceFile, propName, propValue);

		assertNotNull("1.1", manager.getProperty(source, propName));
		assertTrue("1.2", manager.getProperty(source, propName).equals(propValue));
		assertNotNull("1.3", manager.getProperty(sourceFolder, propName));
		assertTrue("1.4", manager.getProperty(sourceFolder, propName).equals(propValue));
		assertNotNull("1.5", manager.getProperty(sourceFile, propName));
		assertTrue("1.6", manager.getProperty(sourceFile, propName).equals(propValue));

		// do the copy at the project level
		manager.copy(source, destination, IResource.DEPTH_INFINITE);

		assertNotNull("1.7", manager.getProperty(destination, propName));
		assertTrue("1.8", manager.getProperty(destination, propName).equals(propValue));

		assertNotNull("1.9", manager.getProperty(destFolder, propName));
		assertTrue("1.10", manager.getProperty(destFolder, propName).equals(propValue));
		assertNotNull("1.11", manager.getProperty(destFile, propName));
		assertTrue("1.12", manager.getProperty(destFile, propName).equals(propValue));

		// do the same thing but copy at the folder level
		manager.deleteProperties(source, IResource.DEPTH_INFINITE);
		manager.deleteProperties(destination, IResource.DEPTH_INFINITE);
		assertNull("2.0", manager.getProperty(source, propName));
		assertNull("2.1", manager.getProperty(sourceFolder, propName));
		assertNull("2.2", manager.getProperty(sourceFile, propName));
		assertNull("2.3", manager.getProperty(destination, propName));
		assertNull("2.4", manager.getProperty(destFolder, propName));
		assertNull("2.5", manager.getProperty(destFile, propName));
		manager.setProperty(sourceFolder, propName, propValue);
		manager.setProperty(sourceFile, propName, propValue);
		assertNotNull("2.6", manager.getProperty(sourceFolder, propName));
		assertTrue("2.7", manager.getProperty(sourceFolder, propName).equals(propValue));
		assertNotNull("2.8", manager.getProperty(sourceFile, propName));
		assertTrue("2.9", manager.getProperty(sourceFile, propName).equals(propValue));

		manager.copy(sourceFolder, destFolder, IResource.DEPTH_INFINITE);

		assertNotNull("2.10", manager.getProperty(destFolder, propName));
		assertTrue("2.11", manager.getProperty(destFolder, propName).equals(propValue));
		assertNotNull("2.12", manager.getProperty(destFile, propName));
		assertTrue("2.13", manager.getProperty(destFile, propName).equals(propValue));

		/* test overwrite */
		String newPropValue = "change property value";
		manager.setProperty(source, propName, newPropValue);
		assertTrue("2.0", manager.getProperty(source, propName).equals(newPropValue));
		manager.copy(source, destination, IResource.DEPTH_INFINITE);
		assertTrue("2.1", manager.getProperty(destination, propName).equals(newPropValue));
	}

	public void testDeleteProperties() throws Throwable {
		/* create common objects */
		IPropertyManager manager = new PropertyManager2((Workspace) ResourcesPlugin.getWorkspace());
		IFile target = projects[0].getFile("target");
		ensureExistsInWorkspace(target, true);

		/* server properties */
		QualifiedName propName = new QualifiedName("eclipse", "prop");
		String propValue = "this is the property value";
		manager.setProperty(target, propName, propValue);
		assertTrue("1.1", manager.getProperty(target, propName).equals(propValue));
		/* delete */
		manager.deleteProperties(target, IResource.DEPTH_INFINITE);
		assertTrue("1.3", manager.getProperty(target, propName) == null);

		//test deep deletion of project properties
		IProject source = projects[0];
		IFolder sourceFolder = source.getFolder("myfolder");
		IResource sourceFile = sourceFolder.getFile("myfile.txt");
		propName = new QualifiedName("test", "prop");
		propValue = "this is the property value";
		ensureExistsInWorkspace(new IResource[] {source, sourceFolder, sourceFile}, true);

		/*
		 * persistent properties
		 */
		manager.setProperty(source, propName, propValue);
		manager.setProperty(sourceFolder, propName, propValue);
		manager.setProperty(sourceFile, propName, propValue);

		assertNotNull("2.1", manager.getProperty(source, propName));
		assertTrue("2.2", manager.getProperty(source, propName).equals(propValue));
		assertNotNull("2.3", manager.getProperty(sourceFolder, propName));
		assertTrue("2.4", manager.getProperty(sourceFolder, propName).equals(propValue));
		assertNotNull("2.5", manager.getProperty(sourceFile, propName));
		assertTrue("2.6", manager.getProperty(sourceFile, propName).equals(propValue));

		//delete properties
		manager.deleteProperties(source, IResource.DEPTH_INFINITE);
		assertNull("3.1", manager.getProperty(source, propName));
		assertNull("3.2", manager.getProperty(sourceFolder, propName));
		assertNull("3.3", manager.getProperty(sourceFile, propName));

	}

	/**
	 * See bug 93849.
	 */
	public void testFileRename() {
		IWorkspaceRoot root = getWorkspace().getRoot();
		IProject project = root.getProject("proj");
		IFolder folder = project.getFolder("folder");
		IFile file1a = folder.getFile("file1");
		ensureExistsInWorkspace(file1a, true);
		QualifiedName key = new QualifiedName(PI_RESOURCES_TESTS, "key");
		try {
			file1a.setPersistentProperty(key, "value");
		} catch (CoreException e) {
			fail("0.5", e);
		}
		try {
			file1a.move(new Path("file2"), true, getMonitor());
		} catch (CoreException e) {
			fail("0.6", e);
		}
		IFile file1b = folder.getFile("file1");
		ensureExistsInWorkspace(file1b, true);
		String value = null;
		try {
			value = file1b.getPersistentProperty(key);
		} catch (CoreException e) {
			fail("0.8", e);
		}
		assertNull("1.0", value);
		file1a = folder.getFile("file2");
		try {
			value = file1a.getPersistentProperty(key);
		} catch (CoreException e) {
			fail("1.9", e);
		}
		assertEquals("2.0", "value", value);

	}

	/**
	 * See bug 93849.
	 */
	public void testFolderRename() {
		IWorkspaceRoot root = getWorkspace().getRoot();
		IProject project = root.getProject("proj");
		IFolder folder1a = project.getFolder("folder1");
		ensureExistsInWorkspace(folder1a, true);
		QualifiedName key = new QualifiedName(PI_RESOURCES_TESTS, "key");
		try {
			folder1a.setPersistentProperty(key, "value");
		} catch (CoreException e) {
			fail("0.5", e);
		}
		try {
			folder1a.move(new Path("folder2"), true, getMonitor());
		} catch (CoreException e) {
			fail("0.6", e);
		}
		IFolder folder1b = project.getFolder("folder1");
		ensureExistsInWorkspace(folder1b, true);
		String value = null;
		try {
			value = folder1b.getPersistentProperty(key);
		} catch (CoreException e) {
			fail("0.8", e);
		}
		assertNull("1.0", value);
		folder1a = project.getFolder("folder2");
		try {
			value = folder1a.getPersistentProperty(key);
		} catch (CoreException e) {
			fail("1.9", e);
		}
		assertEquals("2.0", "value", value);

	}

	/**
	 * Do a stress test by adding a very large property to the store.
	 */
	public void testLargeProperty() {
		// create common objects
		IFile target = projects[0].getFile("target");
		try {
			target.create(getRandomContents(), true, getMonitor());
		} catch (CoreException e) {
			fail("0.0", e);
		}

		QualifiedName name = new QualifiedName("stressTest", "prop");
		final int SIZE = 10000;
		StringBuffer valueBuf = new StringBuffer(SIZE);
		for (int i = 0; i < SIZE; i++) {
			valueBuf.append("a");
		}
		String value = valueBuf.toString();
		try {
			target.setPersistentProperty(name, value);
			//should fail
			fail("1.0");
		} catch (CoreException e) {
			// expected
		}

		// remove trash
		try {
			target.delete(true, getMonitor());
		} catch (CoreException e) {
			fail("20.0", e);
		}
	}

	/**
	 * See bug 93849.
	 */
	public void testProjectRename() {
		IWorkspaceRoot root = getWorkspace().getRoot();
		IProject project1a = root.getProject("proj1");
		ensureExistsInWorkspace(project1a, true);
		QualifiedName key = new QualifiedName(PI_RESOURCES_TESTS, "key");
		try {
			project1a.setPersistentProperty(key, "value");
		} catch (CoreException e) {
			fail("0.5", e);
		}
		try {
			project1a.move(new Path("proj2"), true, getMonitor());
		} catch (CoreException e) {
			fail("0.6", e);
		}
		IProject project1b = root.getProject("proj1");
		ensureExistsInWorkspace(project1b, true);
		String value = null;
		try {
			value = project1b.getPersistentProperty(key);
		} catch (CoreException e) {
			fail("0.8", e);
		}
		assertNull("1.0", value);

		project1a = root.getProject("proj2");
		try {
			value = project1a.getPersistentProperty(key);
		} catch (CoreException e) {
			fail("1.9", e);
		}
		assertEquals("2.0", "value", value);
	}

	public void testProperties() throws Throwable {
		IProgressMonitor monitor = null;

		// create common objects
		IPropertyManager manager = new PropertyManager2((Workspace) ResourcesPlugin.getWorkspace());
		IFile target = projects[0].getFile("target");
		target.create(null, false, monitor);

		// these are the properties that we are going to use
		QualifiedName propName1 = new QualifiedName("org.eclipse.core.tests", "prop1");
		QualifiedName propName2 = new QualifiedName("org.eclipse.core.tests", "prop2");
		QualifiedName propName3 = new QualifiedName("org.eclipse.core.tests", "prop3");
		String propValue1 = "this is the property value1";
		String propValue2 = "this is the property value2";
		String propValue3 = "this is the property value3";
		Vector<StoredProperty> props = new Vector<>(3);
		props.addElement(new StoredProperty(propName1, propValue1));
		props.addElement(new StoredProperty(propName2, propValue2));
		props.addElement(new StoredProperty(propName3, propValue3));

		// set the properties individually and retrieve them
		for (StoredProperty prop : props) {
			manager.setProperty(target, prop.getName(), prop.getStringValue());
			assertEquals("1.0." + prop.getName(), prop.getStringValue(), manager.getProperty(target, prop.getName()));
		}
		// check properties are be appropriately deleted (when set to null)
		for (StoredProperty prop : props) {
			manager.setProperty(target, prop.getName(), null);
			assertEquals("2.0." + prop.getName(), null, manager.getProperty(target, prop.getName()));
		}
		assertEquals("3.0", 0, manager.getProperties(target).size());
		manager.deleteProperties(target, IResource.DEPTH_INFINITE);

		// remove trash
		target.delete(false, monitor);
	}

	public void testSimpleUpdate() {

		// create common objects
		IFile target = projects[0].getFile("target");
		try {
			target.create(getRandomContents(), true, getMonitor());
		} catch (CoreException e) {
			fail("0.0", e);
		}

		// prepare keys and values
		int N = 3;
		QualifiedName[] names = new QualifiedName[3];
		String[] values = new String[N];
		for (int i = 0; i < N; i++) {
			names[i] = new QualifiedName("org.eclipse.core.tests", "prop" + i);
			values[i] = "property value" + i;
		}

		// create properties
		for (int i = 0; i < N; i++) {
			try {
				target.setPersistentProperty(names[i], values[i]);
			} catch (CoreException e) {
				fail("1." + i, e);
			}
		}

		// verify
		for (int i = 0; i < N; i++) {
			try {
				assertTrue("2.0", target.getPersistentProperty(names[i]).equals(values[i]));
			} catch (CoreException e) {
				fail("3." + i, e);
			}
		}

		for (int j = 0; j < 20; j++) {

			// change properties
			for (int i = 0; i < N; i++) {
				try {
					values[i] = values[i] + " - changed";
					target.setPersistentProperty(names[i], values[i]);
				} catch (CoreException e) {
					fail("4." + i, e);
				}
			}

			// verify
			for (int i = 0; i < N; i++) {
				try {
					assertTrue("5.0", target.getPersistentProperty(names[i]).equals(values[i]));
				} catch (CoreException e) {
					fail("6." + i, e);
				}
			}

		}

		// remove trash
		try {
			target.delete(true, getMonitor());
		} catch (CoreException e) {
			fail("20.0", e);
		}
	}

}
