/*******************************************************************************
 * Copyright (c) 2000, 2015 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
 *     Alex Blewitt <alex.blewitt@gmail.com> - Replace new Boolean with Boolean.valueOf - https://bugs.eclipse.org/470244
 *******************************************************************************/
package org.eclipse.core.filebuffers.tests;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertSame;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;

import java.io.PrintStream;
import java.io.PrintWriter;

import org.junit.After;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.TestWatcher;
import org.junit.runner.Description;

import org.eclipse.core.filesystem.EFS;
import org.eclipse.core.filesystem.IFileInfo;
import org.eclipse.core.filesystem.IFileStore;

import org.eclipse.core.runtime.ILog;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Path;
import org.eclipse.core.runtime.Platform;
import org.eclipse.core.runtime.Status;

import org.eclipse.core.resources.IProject;

import org.eclipse.core.filebuffers.FileBuffers;
import org.eclipse.core.filebuffers.IFileBuffer;
import org.eclipse.core.filebuffers.ITextFileBuffer;
import org.eclipse.core.filebuffers.ITextFileBufferManager;
import org.eclipse.core.filebuffers.LocationKind;

import org.eclipse.jface.text.IDocument;
import org.eclipse.jface.text.IDocumentExtension4;
import org.eclipse.jface.text.source.IAnnotationModel;

/**
 * FileBufferFunctions
 */
public abstract class FileBufferFunctions {

	private IProject fProject;
	protected ITextFileBufferManager fManager;
	private IPath fPath;


	protected abstract IPath createPath(IProject project) throws Exception;

	protected abstract void setReadOnly(boolean state) throws Exception;

	protected abstract boolean modifyUnderlyingFile() throws Exception;

	protected abstract boolean deleteUnderlyingFile() throws Exception;

	protected abstract IPath moveUnderlyingFile() throws Exception;

	protected abstract boolean isStateValidationSupported();

	protected abstract Class<IAnnotationModel> getAnnotationModelClass() throws Exception;


	@Before
	public void setUp() throws Exception {
		fManager= FileBuffers.getTextFileBufferManager();
		fProject= ResourceHelper.createProject("project");
		fPath= createPath(fProject);
		ITextFileBuffer buffer= fManager.getTextFileBuffer(fPath, LocationKind.NORMALIZE);
		assertTrue(buffer == null);
	}

	protected IProject getProject() {
		return fProject;
	}

	@After
	public void tearDown() {
		ITextFileBuffer buffer= fManager.getTextFileBuffer(fPath, LocationKind.NORMALIZE);
		assertTrue(buffer == null);
		ResourceHelper.deleteProject("project");
	}

	protected IPath getPath() {
		return fPath;
	}

	@Rule
	public TestFailReporter failReporter= new TestFailReporter();

	public static class TestFailReporter extends TestWatcher {

		private static final String BUNDLE_ID= "org.eclipse.core.filebuffers.tests";

		ILog log= Platform.getLog(Platform.getBundle(BUNDLE_ID));

		@Override
		protected void failed(Throwable e, Description description) {
			IStatus status= new Status(IStatus.ERROR, BUNDLE_ID, "FAIL in " + description, e);
			log.log(status);
		}

		@Override
		protected void succeeded(Description description) {
			IStatus status= new Status(IStatus.INFO, BUNDLE_ID, "PASS in " + description);
			log.log(status);
		}
	}

	/*
	 * Tests getLocation.
	 */
	@Test
	public void test1() throws Exception {
		fManager.connect(fPath, LocationKind.NORMALIZE, null);
		try {
			ITextFileBuffer buffer= fManager.getTextFileBuffer(fPath, LocationKind.NORMALIZE);
			assertEquals(fPath, buffer.getLocation());

		} finally {
			fManager.disconnect(fPath, LocationKind.NORMALIZE, null);
		}
	}

	/*
	 * Tests isSynchronized.
	 */
	@Test
	public void test2() throws Exception {
		fManager.connect(fPath, LocationKind.NORMALIZE, null);
		try {
			ITextFileBuffer fileBuffer= fManager.getTextFileBuffer(fPath, LocationKind.NORMALIZE);
			assertTrue(fileBuffer.isSynchronized());
			IFileStore fileStore= FileBuffers.getFileStoreAtLocation(fPath);
			IFileInfo fileInfo= fileStore.fetchInfo();
			fileInfo.setLastModified(1000);
			if (fileInfo.exists())
				fileStore.putInfo(fileInfo, EFS.SET_LAST_MODIFIED, null);
			long lastModified= fileStore.fetchInfo().getLastModified();
			assertTrue(lastModified == EFS.NONE || !fileBuffer.isSynchronized());

		} finally {
			fManager.disconnect(fPath, LocationKind.NORMALIZE, null);
		}
	}

	/*
	 * Tests isDirty.
	 */
	@Test
	public void test3() throws Exception {
		fManager.connect(fPath, LocationKind.NORMALIZE, null);
		try {
			ITextFileBuffer fileBuffer= fManager.getTextFileBuffer(fPath, LocationKind.NORMALIZE);
			assertFalse(fileBuffer.isDirty());
			IDocument document= fileBuffer.getDocument();
			document.replace(document.getLength(), 0, "appendix");
			assertTrue(fileBuffer.isDirty());

		} finally {
			fManager.disconnect(fPath, LocationKind.NORMALIZE, null);
		}
	}

	/*
	 * Tests isShared.
	 */
	@Test
	public void test4() throws Exception {
		fManager.connect(fPath, LocationKind.NORMALIZE, null);
		try {
			ITextFileBuffer fileBuffer1= fManager.getTextFileBuffer(fPath, LocationKind.NORMALIZE);
			assertFalse(fileBuffer1.isShared());

			fManager.connect(fPath, LocationKind.NORMALIZE, null);
			try {
				ITextFileBuffer fileBuffer2= fManager.getTextFileBuffer(fPath, LocationKind.NORMALIZE);
				assertTrue(fileBuffer1.isShared());
				assertTrue(fileBuffer2.isShared());
			} finally {
				fManager.disconnect(fPath, LocationKind.NORMALIZE, null);
			}

			assertFalse(fileBuffer1.isShared());

		} finally {
			fManager.disconnect(fPath, LocationKind.NORMALIZE, null);
		}
	}

	/*
	 * Tests getModificationStamp.
	 */
	@Test
	public void test5() throws Exception {
		fManager.connect(fPath, LocationKind.NORMALIZE, null);
		try {
			ITextFileBuffer fileBuffer= fManager.getTextFileBuffer(fPath, LocationKind.NORMALIZE);
			long modificationStamp= fileBuffer.getModificationStamp();
			IFileStore fileStore= FileBuffers.getFileStoreAtLocation(fPath);
			IFileInfo fileInfo= fileStore.fetchInfo();
			assertEquals(modificationStamp != IDocumentExtension4.UNKNOWN_MODIFICATION_STAMP, fileInfo.exists());
			fileInfo.setLastModified(1000);
			if (fileInfo.exists())
				fileStore.putInfo(fileInfo, EFS.SET_LAST_MODIFIED, null);
			long lastModified= fileStore.fetchInfo().getLastModified();
			assertTrue(lastModified == EFS.NONE || modificationStamp != fileBuffer.getModificationStamp());
		} finally {
			fManager.disconnect(fPath, LocationKind.NORMALIZE, null);
		}
	}

	/*
	 * Test revert.
	 */
	@Test
	public void test6() throws Exception {
		fManager.connect(fPath, LocationKind.NORMALIZE, null);
		try {

			ITextFileBuffer fileBuffer= fManager.getTextFileBuffer(fPath, LocationKind.NORMALIZE);
			// set dirty bit
			IDocument document= fileBuffer.getDocument();
			String originalContent= document.get();
			document.replace(document.getLength(), 0, "appendix");
			// invalidate synchronization state
			IFileStore fileStore= FileBuffers.getFileStoreAtLocation(fPath);
			IFileInfo fileInfo= fileStore.fetchInfo();
			fileInfo.setLastModified(1000);
			if (fileInfo.exists())
				fileStore.putInfo(fileInfo, EFS.SET_LAST_MODIFIED, null);
			//revert
			fileBuffer.revert(null);
			// check assertions
			assertEquals(originalContent, document.get());
			assertFalse(fileBuffer.isDirty());
			assertTrue(fileBuffer.isSynchronized());

		} finally {
			fManager.disconnect(fPath, LocationKind.NORMALIZE, null);
		}
	}

	/*
	 * Test commit.
	 */
	@Test
	public void test7() throws Exception {
		fManager.connect(fPath, LocationKind.NORMALIZE, null);
		try {

			ITextFileBuffer fileBuffer= fManager.getTextFileBuffer(fPath, LocationKind.NORMALIZE);
			// set dirty bit
			IDocument document= fileBuffer.getDocument();
			document.replace(document.getLength(), 0, "appendix");
			String originalContent= document.get();
			// commit
			fileBuffer.commit(null, true);
			// check assertions
			assertEquals(originalContent, document.get());
			assertFalse(fileBuffer.isDirty());
			assertTrue(fileBuffer.isSynchronized());
			// revert to see effect is persistent
			fileBuffer.revert(null);
			// check assertions
			assertEquals(originalContent, document.get());
			assertFalse(fileBuffer.isDirty());
			assertTrue(fileBuffer.isSynchronized());
			// disconnect
			fManager.disconnect(fPath, LocationKind.NORMALIZE, null);
			// reconnect
			fManager.connect(fPath, LocationKind.NORMALIZE, null);
			try {
				fileBuffer= fManager.getTextFileBuffer(fPath, LocationKind.NORMALIZE);
				document= fileBuffer.getDocument();
				// check assertions
				assertEquals(originalContent, document.get());
				assertFalse(fileBuffer.isDirty());
				assertTrue(fileBuffer.isSynchronized());
			} finally {
				fManager.disconnect(fPath, LocationKind.NORMALIZE, null);
			}

		} finally {
			fManager.disconnect(fPath, LocationKind.NORMALIZE, null);
		}
	}

	/*
	 * Test validateState.
	 */
	@Test
	public void test8_1() throws Exception {
		fManager.connect(fPath, LocationKind.NORMALIZE, null);
		try {

			ITextFileBuffer fileBuffer= fManager.getTextFileBuffer(fPath, LocationKind.NORMALIZE);
			fileBuffer.validateState(null, null);
			assertTrue(fileBuffer.isStateValidated());

		} finally {
			fManager.disconnect(fPath, LocationKind.NORMALIZE, null);
		}
	}

	/*
	 * Test validateState.
	 */
	@Test
	public void test8_2() throws Exception {
		fManager.connect(fPath, LocationKind.NORMALIZE, null);
		try {

			setReadOnly(true);
			ITextFileBuffer fileBuffer= fManager.getTextFileBuffer(fPath, LocationKind.NORMALIZE);
			fileBuffer.validateState(null, null);
			assertTrue(fileBuffer.isStateValidated());

		} finally {
			setReadOnly(false);
			fManager.disconnect(fPath, LocationKind.NORMALIZE, null);
		}
	}

	/*
	 * Test resetStateValidation.
	 */
	@Test
	public void test9_1() throws Exception {
		fManager.connect(fPath, LocationKind.NORMALIZE, null);
		try {

			ITextFileBuffer fileBuffer= fManager.getTextFileBuffer(fPath, LocationKind.NORMALIZE);
			fileBuffer.validateState(null, null);
			fileBuffer.resetStateValidation();
			if (isStateValidationSupported())
				assertFalse(fileBuffer.isStateValidated());

		} finally {
			fManager.disconnect(fPath, LocationKind.NORMALIZE, null);
		}
	}

	/*
	 * Test resetStateValidation.
	 */
	@Test
	public void test9_2() throws Exception {
		fManager.connect(fPath, LocationKind.NORMALIZE, null);
		try {

			setReadOnly(true);
			ITextFileBuffer fileBuffer= fManager.getTextFileBuffer(fPath, LocationKind.NORMALIZE);
			fileBuffer.validateState(null, null);
			fileBuffer.resetStateValidation();
			if (isStateValidationSupported())
				assertFalse(fileBuffer.isStateValidated());

		} finally {
			setReadOnly(false);
			fManager.disconnect(fPath, LocationKind.NORMALIZE, null);
		}
	}

	/*
	 * Test IFileBufferListener#bufferCreated and IFileBufferListener#bufferDisposed
	 */
	@Test
	public void test10() throws Exception {
		class Listener extends FileBufferListener {

			public IFileBuffer buffer;
			public int count;

			@Override
			public void bufferCreated(IFileBuffer buf) {
				++count;
				this.buffer= buf;
			}

			@Override
			public void bufferDisposed(IFileBuffer buf) {
				--count;
				this.buffer= buf;
			}
		}

		Listener listener= new Listener();
		fManager.addFileBufferListener(listener);
		try {

			fManager.connect(fPath, LocationKind.NORMALIZE, null);

			assertEquals(1, listener.count);
			assertNotNull(listener.buffer);
			IFileBuffer fileBuffer= fManager.getFileBuffer(fPath, LocationKind.NORMALIZE);
			assertSame(fileBuffer, listener.buffer);

			fManager.disconnect(fPath, LocationKind.NORMALIZE, null);
			assertEquals(0, listener.count);
			assertSame(fileBuffer, listener.buffer);

		} finally {
			try {
				fManager.disconnect(fPath, LocationKind.NORMALIZE, null);
			} finally {
				fManager.removeFileBufferListener(listener);
			}
		}
	}

	/*
	 * Test IFileBufferListener#dirtyStateChanged
	 */
	@Test
	public void test11_1() throws Exception {
		class Listener extends FileBufferListener {

			public IFileBuffer buffer;
			public int count;
			public boolean isDirty;

			@Override
			public void dirtyStateChanged(IFileBuffer buf, boolean state) {
				++count;
				this.buffer= buf;
				this.isDirty= state;
			}
		}

		Listener listener= new Listener();
		fManager.addFileBufferListener(listener);
		try {

			ITextFileBuffer fileBuffer= fManager.getTextFileBuffer(fPath, LocationKind.NORMALIZE);
			assertTrue(listener.count == 0 && listener.buffer == null);

			fManager.connect(fPath, LocationKind.NORMALIZE, null);
			try {

				fileBuffer= fManager.getTextFileBuffer(fPath, LocationKind.NORMALIZE);
				IDocument document= fileBuffer.getDocument();
				document.replace(0, 0, "prefix");

				assertEquals(1, listener.count);
				assertSame(fileBuffer, listener.buffer);
				assertTrue(listener.isDirty);

				fileBuffer.commit(null, true);

				assertEquals(2, listener.count);
				assertSame(fileBuffer, listener.buffer);
				assertFalse(listener.isDirty);

			} finally {
				fManager.disconnect(fPath, LocationKind.NORMALIZE, null);
			}

		} finally {
			fManager.removeFileBufferListener(listener);
		}
	}

	/*
	 * Test IFileBufferListener#dirtyStateChanged
	 */
	@Test
	public void test11_2() throws Exception {
		class Listener extends FileBufferListener {

			public IFileBuffer buffer;
			public int count;
			public boolean isDirty;

			@Override
			public void dirtyStateChanged(IFileBuffer buf, boolean state) {
				++count;
				this.buffer= buf;
				this.isDirty= state;
			}
		}

		Listener listener= new Listener();
		fManager.addFileBufferListener(listener);
		try {
			ITextFileBuffer fileBuffer= fManager.getTextFileBuffer(fPath, LocationKind.NORMALIZE);
			assertTrue(listener.count == 0 && listener.buffer == null);

			fManager.connect(fPath, LocationKind.NORMALIZE, null);
			try {

				fileBuffer= fManager.getTextFileBuffer(fPath, LocationKind.NORMALIZE);
				IDocument document= fileBuffer.getDocument();
				document.replace(0, 0, "prefix");

				assertEquals(1, listener.count);
				assertSame(fileBuffer, listener.buffer);
				assertTrue(listener.isDirty);

				fileBuffer.revert(null);

				assertEquals(2, listener.count);
				assertSame(fileBuffer, listener.buffer);
				assertFalse(listener.isDirty);

			} finally {
				fManager.disconnect(fPath, LocationKind.NORMALIZE, null);
			}

		} finally {
			fManager.removeFileBufferListener(listener);
		}
	}

	/*
	 * Test IFileBufferListener#bufferContentAboutToBeReplaced/replaced
	 */
	@Test
	public void test12_1() throws Exception {
		class Listener extends FileBufferListener {

			public IFileBuffer preBuffer, postBuffer;
			public int preCount, postCount;

			@Override
			public void bufferContentAboutToBeReplaced(IFileBuffer buffer) {
				++preCount;
				preBuffer= buffer;
			}

			@Override
			public void bufferContentReplaced(IFileBuffer buffer) {
				++postCount;
				postBuffer= buffer;
			}
		}

		Listener listener= new Listener();
		fManager.addFileBufferListener(listener);
		try {
			ITextFileBuffer fileBuffer= fManager.getTextFileBuffer(fPath, LocationKind.NORMALIZE);
			assertTrue(listener.preCount == 0 && listener.postCount == 0 && listener.preBuffer == null && listener.postBuffer == null);

			fManager.connect(fPath, LocationKind.NORMALIZE, null);
			try {

				fileBuffer= fManager.getTextFileBuffer(fPath, LocationKind.NORMALIZE);
				IDocument document= fileBuffer.getDocument();
				document.replace(0, 0, "prefix");

				fileBuffer.revert(null);

				assertEquals(1, listener.preCount);
				assertSame(fileBuffer, listener.preBuffer);
				assertEquals(1, listener.postCount);
				assertSame(fileBuffer, listener.postBuffer);

			} finally {
				fManager.disconnect(fPath, LocationKind.NORMALIZE, null);
			}

		} finally {
			fManager.removeFileBufferListener(listener);
		}
	}

	/*
	 * Test IFileBufferListener#bufferContentAboutToBeReplaced/replaced
	 */
	@Test
	public void test12_2() throws Exception {
		class Listener extends FileBufferListener {

			public IFileBuffer preBuffer, postBuffer;
			public int preCount, postCount;

			@Override
			public void bufferContentAboutToBeReplaced(IFileBuffer buffer) {
				++preCount;
				preBuffer= buffer;
			}

			@Override
			public void bufferContentReplaced(IFileBuffer buffer) {
				++postCount;
				postBuffer= buffer;
			}
		}

		Listener listener= new Listener();
		fManager.addFileBufferListener(listener);
		try {
			ITextFileBuffer fileBuffer= fManager.getTextFileBuffer(fPath, LocationKind.NORMALIZE);
			assertTrue(listener.preCount == 0 && listener.postCount == 0 && listener.preBuffer == null && listener.postBuffer == null);

			fManager.connect(fPath, LocationKind.NORMALIZE, null);
			try {

				fileBuffer= fManager.getTextFileBuffer(fPath, LocationKind.NORMALIZE);

				if (modifyUnderlyingFile()) {
					assertEquals(1, listener.preCount);
					assertSame(fileBuffer, listener.preBuffer);
					assertEquals(1, listener.postCount);
					assertSame(fileBuffer, listener.postBuffer);
				}

			} finally {
				fManager.disconnect(fPath, LocationKind.NORMALIZE, null);
			}

		} finally {
			fManager.removeFileBufferListener(listener);
		}
	}

	/*
	 * Test IFileBufferListener#stateValidationChanged
	 */
	@Test
	public void test13_1() throws Exception {
		class Listener extends FileBufferListener {

			public IFileBuffer buffer;
			public int count;
			public boolean isStateValidated;

			@Override
			public void stateValidationChanged(IFileBuffer buf, boolean state) {
				++count;
				this.buffer= buf;
				this.isStateValidated= state;
			}
		}

		Listener listener= new Listener();
		fManager.addFileBufferListener(listener);
		try {
			ITextFileBuffer fileBuffer= fManager.getTextFileBuffer(fPath, LocationKind.NORMALIZE);
			assertTrue(listener.count == 0 && listener.buffer == null);

			fManager.connect(fPath, LocationKind.NORMALIZE, null);
			try {

				fileBuffer= fManager.getTextFileBuffer(fPath, LocationKind.NORMALIZE);
				fileBuffer.validateState(null, null);

				if (isStateValidationSupported()) {
					assertEquals(1, listener.count);
					assertSame(fileBuffer, listener.buffer);
					assertTrue(listener.isStateValidated);
				}

			} finally {
				fManager.disconnect(fPath, LocationKind.NORMALIZE, null);
			}

		} finally {
			fManager.removeFileBufferListener(listener);
		}
	}

	/*
	 * Test IFileBufferListener#stateValidationChanged
	 */
	@Test
	public void test13_2() throws Exception {
		class Listener extends FileBufferListener {

			public IFileBuffer buffer;
			public int count;
			public boolean isStateValidated;

			@Override
			public void stateValidationChanged(IFileBuffer buf, boolean state) {
				++count;
				this.buffer= buf;
				this.isStateValidated= state;
			}
		}

		Listener listener= new Listener();
		fManager.addFileBufferListener(listener);
		try {
			ITextFileBuffer fileBuffer= fManager.getTextFileBuffer(fPath, LocationKind.NORMALIZE);
			assertTrue(listener.count == 0 && listener.buffer == null);

			fManager.connect(fPath, LocationKind.NORMALIZE, null);
			try {

				setReadOnly(true);
				fileBuffer= fManager.getTextFileBuffer(fPath, LocationKind.NORMALIZE);
				fileBuffer.validateState(null, null);

				if (isStateValidationSupported()) {
					assertEquals(1, listener.count);
					assertSame(fileBuffer, listener.buffer);
					assertTrue(listener.isStateValidated);
				}

			} finally {
				setReadOnly(false);
				fManager.disconnect(fPath, LocationKind.NORMALIZE, null);
			}

		} finally {
			fManager.removeFileBufferListener(listener);
		}
	}
	/*
	 * Test IFileBufferListener#stateValidationChanged
	 */
	@Test
	public void test13_3() throws Exception {
		class Listener extends FileBufferListener {

			public IFileBuffer buffer;
			public int count;
			public boolean isStateValidated;

			@Override
			public void stateValidationChanged(IFileBuffer buf, boolean state) {
				++count;
				this.buffer= buf;
				this.isStateValidated= state;
			}
		}

		Listener listener= new Listener();
		fManager.addFileBufferListener(listener);
		try {
			ITextFileBuffer fileBuffer= fManager.getTextFileBuffer(fPath, LocationKind.NORMALIZE);
			assertTrue(listener.count == 0 && listener.buffer == null);

			fManager.connect(fPath, LocationKind.NORMALIZE, null);
			try {

				fileBuffer= fManager.getTextFileBuffer(fPath, LocationKind.NORMALIZE);
				fileBuffer.validateState(null, null);
				fileBuffer.resetStateValidation();

				if (isStateValidationSupported()) {
					assertEquals(2, listener.count);
					assertSame(fileBuffer, listener.buffer);
					assertFalse(listener.isStateValidated);
				}

			} finally {
				fManager.disconnect(fPath, LocationKind.NORMALIZE, null);
			}

		} finally {
			fManager.removeFileBufferListener(listener);
		}
	}

	/*
	 * Test IFileBufferListener#stateValidationChanged
	 */
	@Test
	public void test13_4() throws Exception {
		class Listener extends FileBufferListener {

			public IFileBuffer buffer;
			public int count;
			public boolean isStateValidated;

			@Override
			public void stateValidationChanged(IFileBuffer buf, boolean state) {
				++count;
				this.buffer= buf;
				this.isStateValidated= state;
			}
		}

		Listener listener= new Listener();
		fManager.addFileBufferListener(listener);
		try {
			ITextFileBuffer fileBuffer= fManager.getTextFileBuffer(fPath, LocationKind.NORMALIZE);
			assertTrue(listener.count == 0 && listener.buffer == null);

			fManager.connect(fPath, LocationKind.NORMALIZE, null);
			try {

				setReadOnly(true);
				fileBuffer= fManager.getTextFileBuffer(fPath, LocationKind.NORMALIZE);
				fileBuffer.validateState(null, null);
				fileBuffer.resetStateValidation();

				if (isStateValidationSupported()) {
					assertEquals(2, listener.count);
					assertSame(fileBuffer, listener.buffer);
					assertFalse(listener.isStateValidated);
				}

			} finally {
				setReadOnly(false);
				fManager.disconnect(fPath, LocationKind.NORMALIZE, null);
			}

		} finally {
			fManager.removeFileBufferListener(listener);
		}
	}

	/*
	 * Test IFileBufferListener#underlyingFileDeleted
	 */
	@Test
	public void test14() throws Exception {
		class Listener extends FileBufferListener {

			public IFileBuffer buffer;
			public int count;

			@Override
			public void underlyingFileDeleted(IFileBuffer buf) {
				++count;
				this.buffer= buf;
			}
		}

		Listener listener= new Listener();
		fManager.addFileBufferListener(listener);
		try {
			ITextFileBuffer fileBuffer= fManager.getTextFileBuffer(fPath, LocationKind.NORMALIZE);
			assertTrue(listener.count == 0 && listener.buffer == null);

			fManager.connect(fPath, LocationKind.NORMALIZE, null);
			try {

				fileBuffer= fManager.getTextFileBuffer(fPath, LocationKind.NORMALIZE);
				if (deleteUnderlyingFile()) {
					assertEquals(1, listener.count);
					assertSame(fileBuffer, listener.buffer);
				}

			} finally {
				fManager.disconnect(fPath, LocationKind.NORMALIZE, null);
			}

		} finally {
			fManager.removeFileBufferListener(listener);
		}
	}

	/*
	 * Test IFileBufferListener#underlyingFileMoved
	 */
	@Test
	public void test15() throws Exception {
		class Listener extends FileBufferListener {

			public IFileBuffer buffer;
			public int count;
			public IPath newLocation;

			@Override
			public void underlyingFileMoved(IFileBuffer buf, IPath location) {
				++count;
				this.buffer= buf;
				this.newLocation= location;
			}
		}

		Listener listener= new Listener();
		fManager.addFileBufferListener(listener);
		try {
			ITextFileBuffer fileBuffer= fManager.getTextFileBuffer(fPath, LocationKind.NORMALIZE);
			assertTrue(listener.count == 0 && listener.buffer == null);

			fManager.connect(fPath, LocationKind.NORMALIZE, null);
			try {

				fileBuffer= fManager.getTextFileBuffer(fPath, LocationKind.NORMALIZE);
				IPath newLocation= moveUnderlyingFile();
				if (newLocation != null) {
					if (listener.count != 1 || listener.buffer != fileBuffer || !newLocation.equals(listener.newLocation)) {
						StringBuilder buf= new StringBuilder();
						buf.append("Wrong listener notifcation in ").append(getClass().getName()).append(":\n");
						buf.append("listener.count: ").append(listener.count).append(" (expected: 1)\n");
						if (newLocation.equals(listener.newLocation))
							buf.append("newLocation identical: true\n");
						else {
							buf.append("listener.newLocation: ").append(listener.newLocation).append("\n");
							buf.append("newLocation: ").append(newLocation).append("\n");
						}
						buf.append("buffers identical: ").append(listener.buffer == fileBuffer);
						fail(buf.toString());
					}
				}

			} finally {
				fManager.disconnect(fPath, LocationKind.NORMALIZE, null);
			}

		} finally {
			fManager.removeFileBufferListener(listener);
		}
	}

	/*
	 * Test IFileBufferListener#stateChanging for external changes
	 */
	@Test
	public void test16_1() throws Exception {
		class Listener extends FileBufferListener {

			public IFileBuffer buffer;
			public int count;

			@Override
			public void stateChanging(IFileBuffer buf) {
				++count;
				this.buffer= buf;
			}
		}

		Listener listener= new Listener();
		fManager.addFileBufferListener(listener);
		try {
			ITextFileBuffer fileBuffer= fManager.getTextFileBuffer(fPath, LocationKind.NORMALIZE);
			assertTrue(listener.count == 0 && listener.buffer == null);

			fManager.connect(fPath, LocationKind.NORMALIZE, null);
			try {

				fileBuffer= fManager.getTextFileBuffer(fPath, LocationKind.NORMALIZE);
				if (modifyUnderlyingFile()) {
					assertSame(listener.buffer, fileBuffer);
					assertEquals(1, listener.count);
				}

			} finally {
				fManager.disconnect(fPath, LocationKind.NORMALIZE, null);
			}

		} finally {
			fManager.removeFileBufferListener(listener);
		}
	}

	/*
	 * Test IFileBufferListener#stateChanging for external changes
	 */
	@Test
	public void test16_2() throws Exception {
		class Listener extends FileBufferListener {

			public IFileBuffer buffer;
			public int count;

			@Override
			public void stateChanging(IFileBuffer buf) {
				++count;
				this.buffer= buf;
			}
		}

		Listener listener= new Listener();
		fManager.addFileBufferListener(listener);
		try {
			ITextFileBuffer fileBuffer= fManager.getTextFileBuffer(fPath, LocationKind.NORMALIZE);
			assertTrue(listener.count == 0 && listener.buffer == null);

			fManager.connect(fPath, LocationKind.NORMALIZE, null);
			try {

				fileBuffer= fManager.getTextFileBuffer(fPath, LocationKind.NORMALIZE);
				if (deleteUnderlyingFile()) {
					assertEquals(1, listener.count);
					assertSame(fileBuffer, listener.buffer);
				}

			} finally {
				fManager.disconnect(fPath, LocationKind.NORMALIZE, null);
			}

		} finally {
			fManager.removeFileBufferListener(listener);
		}
	}

	/*
	 * Test IFileBufferListener#stateChanging for external changes
	 */
	@Test
	public void test16_3() throws Exception {
		class Listener extends FileBufferListener {

			public IFileBuffer buffer;
			public int count;

			@Override
			public void stateChanging(IFileBuffer buf) {
				++count;
				this.buffer= buf;
			}
		}

		Listener listener= new Listener();
		fManager.addFileBufferListener(listener);
		try {
			ITextFileBuffer fileBuffer= fManager.getTextFileBuffer(fPath, LocationKind.NORMALIZE);
			assertTrue(listener.count == 0 && listener.buffer == null);

			fManager.connect(fPath, LocationKind.NORMALIZE, null);
			try {

				fileBuffer= fManager.getTextFileBuffer(fPath, LocationKind.NORMALIZE);
				if (moveUnderlyingFile() != null) {
					assertEquals(1, listener.count);
					assertSame(fileBuffer, listener.buffer);
				}

			} finally {
				fManager.disconnect(fPath, LocationKind.NORMALIZE, null);
			}

		} finally {
			fManager.removeFileBufferListener(listener);
		}
	}

	/*
	 * Test IFileBufferListener#stateChanging for internal changes
	 */
	@Test
	public void test17_1() throws Exception {
		class Listener extends FileBufferListener {

			public IFileBuffer buffer;
			public int count;

			@Override
			public void stateChanging(IFileBuffer buf) {
				++count;
				this.buffer= buf;
			}
		}

		Listener listener= new Listener();
		fManager.addFileBufferListener(listener);
		try {
			ITextFileBuffer fileBuffer= fManager.getTextFileBuffer(fPath, LocationKind.NORMALIZE);
			assertTrue(listener.count == 0 && listener.buffer == null);

			fManager.connect(fPath, LocationKind.NORMALIZE, null);
			try {

				fileBuffer= fManager.getTextFileBuffer(fPath, LocationKind.NORMALIZE);
				fileBuffer.validateState(null, null);

				if (isStateValidationSupported()) {
					assertEquals(1, listener.count);
					assertSame(fileBuffer, listener.buffer);
				}

			} finally {
				fManager.disconnect(fPath, LocationKind.NORMALIZE, null);
			}

		} finally {
			fManager.removeFileBufferListener(listener);
		}
	}
	/*
	 * Test IFileBufferListener#stateChanging for internal changes
	 */
	@Test
	public void test17_2() throws Exception {
		class Listener extends FileBufferListener {

			public IFileBuffer buffer;
			public int count;

			@Override
			public void stateChanging(IFileBuffer buf) {
				++count;
				this.buffer= buf;
			}
		}

		Listener listener= new Listener();
		fManager.addFileBufferListener(listener);
		try {
			ITextFileBuffer fileBuffer= fManager.getTextFileBuffer(fPath, LocationKind.NORMALIZE);
			assertTrue(listener.count == 0 && listener.buffer == null);

			fManager.connect(fPath, LocationKind.NORMALIZE, null);
			try {

				fileBuffer= fManager.getTextFileBuffer(fPath, LocationKind.NORMALIZE);
				IDocument document= fileBuffer.getDocument();
				document.replace(0, 0, "prefix");
				fileBuffer.revert(null);

				assertEquals(1, listener.count);
				assertSame(fileBuffer, listener.buffer);

			} finally {
				fManager.disconnect(fPath, LocationKind.NORMALIZE, null);
			}

		} finally {
			fManager.removeFileBufferListener(listener);
		}
	}

	/*
	 * Test IFileBufferListener#stateChanging for internal changes
	 */
	@Test
	public void test17_3() throws Exception {
		class Listener extends FileBufferListener {

			public IFileBuffer buffer;
			public int count;

			@Override
			public void stateChanging(IFileBuffer buf) {
				++count;
				this.buffer= buf;
			}
		}

		Listener listener= new Listener();
		fManager.addFileBufferListener(listener);
		try {
			ITextFileBuffer fileBuffer= fManager.getTextFileBuffer(fPath, LocationKind.NORMALIZE);
			assertTrue(listener.count == 0 && listener.buffer == null);

			fManager.connect(fPath, LocationKind.NORMALIZE, null);
			try {

				fileBuffer= fManager.getTextFileBuffer(fPath, LocationKind.NORMALIZE);
				IDocument document= fileBuffer.getDocument();
				document.replace(0, 0, "prefix");
				fileBuffer.commit(null, true);

				assertEquals(1, listener.count);
				assertSame(fileBuffer, listener.buffer);

			} finally {
				fManager.disconnect(fPath, LocationKind.NORMALIZE, null);
			}

		} finally {
			fManager.removeFileBufferListener(listener);
		}
	}

	/*
	 * Test annotation model existence.
	 * ATTENTION: This test is only effective in a workspace that contains the "org.eclipse.ui.editors" bundle.
	 */
	@Test
	public void test18() throws Exception {
		fManager.connect(fPath, LocationKind.NORMALIZE, null);
		try {
			ITextFileBuffer buffer= fManager.getTextFileBuffer(fPath, LocationKind.NORMALIZE);
			assertNotNull(buffer);

			Class<IAnnotationModel> clazz= getAnnotationModelClass();
			if (clazz != null) {
				IAnnotationModel model= buffer.getAnnotationModel();
				assertTrue(clazz.isInstance(model));
			}

		} finally {
			fManager.disconnect(fPath, LocationKind.NORMALIZE, null);
		}
	}

	/*
	 * Test notification in case of failing listener.
	 */
	@Test
	public void test19() throws Exception {

		class NotifiedListener extends FileBufferListener {

			int notifyCount= 0;

			@Override
			public void bufferCreated(IFileBuffer buffer) {
				notifyCount++;
			}
			@Override
			public void bufferDisposed(IFileBuffer buffer) {
				notifyCount++;
			}
		}

		class ForcedException extends RuntimeException {
			private static final long serialVersionUID= 1L;

			@Override
			public void printStackTrace(PrintStream s) {
				s.println("!FORCED BY TEST: this entry is intentional");
			}

			@Override
			public void printStackTrace(PrintWriter s) {
				s.println("!FORCED BY TEST: this entry is intentional");
			}
		}

		NotifiedListener notifyCounter1= new NotifiedListener();
		NotifiedListener notifyCounter2= new NotifiedListener();

		FileBufferListener failingListener= new FileBufferListener() {
			@Override
			public void bufferCreated(IFileBuffer buffer) {
				throw new ForcedException();
			}
			@Override
			public void bufferDisposed(IFileBuffer buffer) {
				throw new ForcedException();
			}
		};

		fManager.addFileBufferListener(notifyCounter1);
		fManager.addFileBufferListener(failingListener);
		fManager.addFileBufferListener(notifyCounter2);

		fManager.connect(fPath, LocationKind.NORMALIZE, null);
		try {
			ITextFileBuffer buffer= fManager.getTextFileBuffer(fPath, LocationKind.NORMALIZE);
			assertNotNull(buffer);

			Class<IAnnotationModel> clazz= getAnnotationModelClass();
			if (clazz != null) {
				IAnnotationModel model= buffer.getAnnotationModel();
				assertTrue(clazz.isInstance(model));
			}

		} finally {
			fManager.disconnect(fPath, LocationKind.NORMALIZE, null);
			fManager.removeFileBufferListener(notifyCounter1);
			fManager.removeFileBufferListener(failingListener);
			fManager.removeFileBufferListener(notifyCounter2);
		}

		assertEquals(2, notifyCounter1.notifyCount);
		assertEquals(2, notifyCounter2.notifyCount);
	}

	@Test
	public void testGetBufferForDocument() throws Exception {
		fManager.connect(fPath, LocationKind.NORMALIZE, null);
		try {
			ITextFileBuffer buffer= fManager.getTextFileBuffer(fPath, LocationKind.NORMALIZE);
			assertNotNull(buffer);
			IDocument document= buffer.getDocument();
			assertNotNull(document);
			assertSame(buffer, fManager.getTextFileBuffer(document));
		} finally {
			fManager.disconnect(fPath, LocationKind.NORMALIZE, null);
		}
	}

	/*
	 * Tests isSynchronized.
	 */
	@Test
	public void testGetFileStoreAnnotationModel() throws Exception {
		IFileStore fileStore= EFS.getNullFileSystem().getStore(new Path("/dev/null"));
		assertNotNull(fileStore);
		fManager.connectFileStore(fileStore, null);
		try {
			ITextFileBuffer fileBuffer= fManager.getFileStoreTextFileBuffer(fileStore);
			IAnnotationModel model= fileBuffer.getAnnotationModel();
			Class<IAnnotationModel> clazz= getAnnotationModelClass();
			if (clazz != null)
				assertTrue(clazz.isInstance(model));
			else
				assertNotNull(model);
		} finally {
			fManager.disconnectFileStore(fileStore, null);
		}
	}

	@Test
	public void testGetFileBuffers() throws Exception {
		fManager.connect(fPath, LocationKind.NORMALIZE, null);
		try {
			ITextFileBuffer buffer= fManager.getTextFileBuffer(fPath, LocationKind.NORMALIZE);
			assertNotNull(buffer);
			IFileBuffer[] fileBuffers= fManager.getFileBuffers();
			assertNotNull(fileBuffers);
			assertEquals(1, fileBuffers.length);
			assertSame(buffer, fileBuffers[0]);
			fileBuffers= fManager.getFileStoreFileBuffers();
			assertNotNull(fileBuffers);
			assertEquals(0, fileBuffers.length);
		} finally {
			fManager.disconnect(fPath, LocationKind.NORMALIZE, null);
		}
	}

}
