/*******************************************************************************
* Copyright (c) 2009 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
* Zend Technologies
*******************************************************************************/
package org.eclipse.php.core.tests.document.partitioner;
import static org.junit.Assert.assertSame;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.net.URL;
import java.util.ArrayList;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IWorkspace;
import org.eclipse.core.resources.IWorkspaceRoot;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.FileLocator;
import org.eclipse.core.runtime.Platform;
import org.eclipse.jface.text.ITypedRegion;
import org.eclipse.php.core.tests.PHPCoreTests;
import org.eclipse.php.core.tests.TestSuiteWatcher;
import org.eclipse.php.core.tests.TestUtils;
import org.eclipse.php.internal.core.documentModel.partitioner.PHPPartitionTypes;
import org.eclipse.php.internal.core.documentModel.partitioner.PHPStructuredTextPartitioner;
import org.eclipse.wst.sse.core.StructuredModelManager;
import org.eclipse.wst.sse.core.internal.provisional.IStructuredModel;
import org.eclipse.wst.sse.core.internal.provisional.text.IStructuredDocument;
import org.junit.After;
import org.junit.Before;
import org.junit.ClassRule;
import org.junit.Test;
import org.junit.rules.TestWatcher;
/**
* Description: This class tests {@link PHPStructuredTextPartitioner} Each
* method checks a different situation in which a PHP partition can appear.
* Certain markers contained in the PHP markers are looked for each time.
*
* @author Alon Peled
*/
public class PHPPartitionerTests {
@ClassRule
public static TestWatcher watcher = new TestSuiteWatcher();
private static final String PROJECT_NAME = "partitioner";
// The markers looked for in the PHP partition
private static final String[] phpLookUp = { "php", "echo", "PHP_Single_Comment", "PHP_Multi_Comment", "PHP_Doc",
"Test quoted string partition", "1 F d, Y", "Running test", "$num" };
protected static IProject project;
protected static IFile testFile;
public File getSourceWorkspacePath() {
return new File(getPluginDirectoryPath(), "workspace");
}
/**
* Returns the OS path to the directory that contains this plugin.
*/
protected File getPluginDirectoryPath() {
try {
URL platformURL = Platform.getBundle(PHPCoreTests.PLUGIN_ID).getEntry("/");
return new File(FileLocator.toFileURL(platformURL).getFile());
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
/**
* Returns the IWorkspace this test suite is running on.
*/
public static IWorkspace getWorkspace() {
return ResourcesPlugin.getWorkspace();
}
public static IWorkspaceRoot getWorkspaceRoot() {
return getWorkspace().getRoot();
}
/**
* Copy the given source directory (and all its contents) to the given
* target directory.
*/
protected void copyDirectory(File source, File target) throws IOException {
if (!target.exists()) {
target.mkdirs();
}
File[] files = source.listFiles();
if (files == null)
return;
for (int i = 0; i < files.length; i++) {
File sourceChild = files[i];
String name = sourceChild.getName();
if (name.equals("CVS") || name.equals(".svn"))
continue;
File targetChild = new File(target, name);
if (sourceChild.isDirectory()) {
copyDirectory(sourceChild, targetChild);
} else {
copy(sourceChild, targetChild);
}
}
}
/**
* Copy file from src (path to the original file) to dest (path to the
* destination file).
*/
public static void copy(File src, File dest) throws IOException {
InputStream in = null;
OutputStream out = null;
byte[] buffer = new byte[12 * 1024];
int read;
try {
in = new FileInputStream(src);
try {
out = new FileOutputStream(dest);
while ((read = in.read(buffer)) != -1) {
out.write(buffer, 0, read);
}
} finally {
if (out != null) {
out.close();
}
}
} finally {
if (in != null) {
in.close();
}
}
}
@Before
public void setUp() throws Exception {
// copy files in project from source workspace to target workspace
final File sourceWorkspacePath = getSourceWorkspacePath();
final File targetWorkspacePath = getWorkspaceRoot().getLocation().toFile();
copyDirectory(new File(sourceWorkspacePath, PROJECT_NAME), new File(targetWorkspacePath, PROJECT_NAME));
project = TestUtils.createProject(PROJECT_NAME);
}
@After
public void tearDown() throws Exception {
TestUtils.deleteProject(project);
}
/**
* Test PHP partition inside HTML
*
* @throws Exception
*/
@Test
public void partitionInHTML() throws Exception {
ArrayList<String> matches = getPartitionType(phpLookUp, "phpPartitionerTestHTML.php");
for (int i = 0; i < matches.size(); i++) {
assertSame(PHPPartitionTypes.PHP_DEFAULT, (String) matches.get(i));
}
}
/**
* Test PHP partition in a PHP-only file
*
* @throws Exception
*/
@Test
public void partitionStandalone() throws Exception {
ArrayList<String> matches = getPartitionType(phpLookUp, "phpPartitionerTestPhp.php");
for (int i = 0; i < matches.size(); i++) {
assertSame(PHPPartitionTypes.PHP_DEFAULT, (String) matches.get(i));
}
}
/**
* Test PHP partition in HTML when PHP is an HTML attribute key
*
* @throws Exception
*/
@Test
public void partitionPhpAsHTMLAttributeKey() throws Exception {
ArrayList<String> matches = getPartitionType(phpLookUp, "phpPartitionerTestPhpAsHTMLAttributeKey.php");
for (int i = 0; i < matches.size(); i++) {
assertSame(PHPPartitionTypes.PHP_DEFAULT, (String) matches.get(i));
}
}
/**
* Test PHP partition in HTML when PHP is an HTML attribute value
*
* @throws Exception
*/
@Test
public void partitionPhpAsHTMLAttributeValue() throws Exception {
ArrayList<String> matches = getPartitionType(phpLookUp, "phpPartitionerTestPhpAsHTMLAttributeValue.php");
for (int i = 0; i < matches.size(); i++) {
assertSame(PHPPartitionTypes.PHP_DEFAULT, (String) matches.get(i));
}
}
/**
* This method invokes the partitioner, and returns the partition type of
* each marker
*
* @param markers
* Strings to be looked for in the file, which have the same
* partiotion type
* @param preferOpenPartitions
* @return a Vector of partition types, all are expected to be with the same
* type
* @throws Exception
*/
@SuppressWarnings("restriction")
private ArrayList<String> getPartitionType(String[] markers, String testDataFile) throws Exception {
// offset from beginning of stream
int offset = 0;
ArrayList<String> results = new ArrayList<String>();
// init files
IFile inFile = project.getFile(testDataFile);
// open streams
InputStreamReader inStream = new InputStreamReader(inFile.getContents());
BufferedReader reader = new BufferedReader(inStream);
final IStructuredModel modelForEdit = StructuredModelManager.getModelManager().getModelForEdit(inFile);
try {
final IStructuredDocument structuredDocument = modelForEdit.getStructuredDocument();
// create the partitioner
final PHPStructuredTextPartitioner structuredTextPartitioner = new PHPStructuredTextPartitioner();
structuredTextPartitioner.connect(structuredDocument);
// go over the file, one line at a time, and search for the markers
String curLine = reader.readLine();
int lineNumber = 0;
while (curLine != null) {
for (int i = 0; i < markers.length; i++) {
int lineOffset = curLine.indexOf(markers[i]);
// if marker was found in current line, get partition type
if (lineOffset != -1) {
ITypedRegion partition = structuredTextPartitioner.getPartition(offset + lineOffset);
results.add(partition.getType());
}
}
// update global offset
String curLineDelimiter = structuredDocument.getLineDelimiter(lineNumber);
// use original line endings to shift the offset
offset += curLine.length() + (curLineDelimiter != null ? curLineDelimiter.length() : 0);
curLine = reader.readLine();
lineNumber++;
}
} finally {
reader.close();
if (modelForEdit != null) {
modelForEdit.releaseFromEdit();
}
}
return results;
}
}