/*******************************************************************************
 * Copyright (c) 2000, 2017 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
 *     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;
		StringBuilder valueBuf = new StringBuilder(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);
		}
	}

}
