blob: 00101887f0ddb785ca535759ae2ea03d1fcd1898 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2008 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.jdt.ui.tests.chkpii;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.Writer;
import java.net.URL;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.regex.Pattern;
import junit.framework.TestCase;
import org.eclipse.jdt.testplugin.JavaTestPlugin;
import org.eclipse.core.runtime.FileLocator;
import org.eclipse.jdt.internal.ui.util.StringMatcher;
/**
* Runs the 'tidy' command (e.g. from Cygwin) on HTML files in the workspace
* and collects HTMLTidy's errors and warnings into /chkpiiResults/tidy.txt
*
* Note: Currently disabled.
*/
public class HTMLTidyTest extends TestCase {
private static final int TIDY_TIMEOUT= 10000;
private static final Pattern EXCLUSION_PATTERN_TABLE_SUMMARY= Pattern.compile("line \\d+ column \\d+ - Warning: <table> lacks \"summary\" attribute");
private static final Pattern EXCLUSION_PATTERN_EMPTY_TAG= Pattern.compile("line \\d+ column \\d+ - Warning: trimming empty <\\w+>");
private static final Pattern EXCLUSION_PATTERN_MALFORMED_URI= Pattern.compile("line \\d+ column \\d+ - Warning: <a> escaping malformed URI reference");
private static final Pattern eXCLUSION_PATTERN_SCRIPT_TYPE= Pattern.compile("line \\d+ column \\d+ - Warning: <script> inserting \"type\" attribute");
private static final Pattern eXCLUSION_PATTERN_IMG_LACKS_ALT= Pattern.compile("line \\d+ column \\d+ - Warning: <img> lacks \"alt\" attribute");
private int fworkspacePathLength;
private StringMatcher[] fIgnores;
private Writer fTidyResults;
/**
* Main method for manual testing of a file or folder selected in the workspace. To run, create
* a Java launch configuration with program argument<br>
* <code>"${resource_loc}"</code><br>
* (including double quotes!).
*
* @param args 1 argument: Absolute path to a file or folder
* @throws Exception if checking fails
*/
public static void main(String[] args) throws Exception {
HTMLTidyTest test= new HTMLTidyTest();
test.fIgnores= new StringMatcher[0];
test.fTidyResults= new OutputStreamWriter(System.out);
File file= new File(args[0]);
if (file.isDirectory())
test.checkFolder(file);
else
test.checkFile(file);
}
public void testHTML() throws Exception {
URL testBundleRoot= JavaTestPlugin.getDefault().getBundle().getEntry("/");
URL testBundleFile= FileLocator.toFileURL(testBundleRoot);
File hostWorkspace= new File(testBundleFile.getFile()).getParentFile();
String workspacePath= hostWorkspace.getAbsolutePath();
fworkspacePathLength= workspacePath.length();
File chkpiiResults= new File(hostWorkspace, "chkpiiResults");
File tidy= new File(chkpiiResults, "tidy.txt");
fTidyResults= new OutputStreamWriter(new FileOutputStream(tidy), "UTF-8");
String startTime= new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date());
fTidyResults.write(getClass().getName() + " started at " + startTime + "\n");
fIgnores= getIgnores();
try {
boolean ok= true;
// ok&= checkFolder(new File(hostWorkspace, "org.eclipse.jdt.doc.user"), tidyResults);
// ok&= checkFolder(new File(hostWorkspace, "org.eclipse.jdt.doc.isv"), tidyResults);
// ok&= checkFolder(new File(hostWorkspace, "org.eclipse.platform.doc.user"), tidyResults);
// ok&= checkFolder(new File(hostWorkspace, "org.eclipse.platform.doc.isv"), tidyResults);
// ok&= checkFolder(new File(hostWorkspace + "/org.eclipse.jdt.doc.isv/guide"));
ok&= checkFolder(hostWorkspace);
assertTrue("See " + tidy.getAbsolutePath(), ok);
} finally {
fTidyResults.flush();
fTidyResults.close();
fTidyResults= null;
}
}
private StringMatcher[] getIgnores() throws IOException {
ArrayList matchers= new ArrayList();
InputStream is= getClass().getResourceAsStream("ignoreFiles.txt");
BufferedReader reader= new BufferedReader(new InputStreamReader(is));
while (reader.ready()) {
String line= reader.readLine();
if (line.length() > 0) {
char first= line.charAt(0);
if (line.endsWith("/*"))
line= line.substring(0, line.length() - 2); // stops at directory during tree traversal
if (first != '/' && first != '*') { // relative matches
// emulate CHKPII specification:
// matchers.add(new StringMatcher(fWorkspacePath + "/" + line, true, false));
// emulate actual CHKPII implementation:
matchers.add(new StringMatcher("*/" + line, true, false));
}
matchers.add(new StringMatcher(line, true, false));
}
}
return (StringMatcher[]) matchers.toArray(new StringMatcher[matchers.size()]);
}
private boolean isIgnored(File file) {
String relativePath= file.getAbsolutePath().substring(fworkspacePathLength);
relativePath= relativePath.replace('\\', '/');
for (int i= 0; i < fIgnores.length; i++) {
StringMatcher matcher= fIgnores[i];
if (matcher.match(relativePath))
return true;
}
return false;
}
private boolean checkFolder(File folder) throws Exception {
File[] files= folder.listFiles();
boolean success= true;
for (int i= 0; i < files.length; i++) {
File file= files[i];
if (isIgnored(file)) {
// System.out.println("Ignored: " + file.getAbsolutePath() + (file.isDirectory() ? "/*" : ""));
continue;
}
if (isHTMLFile(file)) {
success&= checkFile(file);
} else if (file.isDirectory()) {
success&= checkFolder(file);
}
}
return success;
}
private boolean checkFile(File file) throws Exception {
String filePath= file.getAbsolutePath();
String command= "tidy -eq \"" + filePath + "\"";
final Process process= Runtime.getRuntime().exec(command);
long timeout= System.currentTimeMillis() + TIDY_TIMEOUT;
BufferedReader tidyReader= new BufferedReader(new InputStreamReader(process.getErrorStream()));
boolean available= tidyReader.ready();
boolean first= true;
while (available || System.currentTimeMillis() < timeout) {
if (! available) {
if (! isAlive(process))
break;
Thread.sleep(100);
} else {
while (available) {
String line= tidyReader.readLine();
if (isRelevant(line)) {
if (first) {
first= false;
fTidyResults.write("\n--- " + filePath +'\n');
}
fTidyResults.write(line);
fTidyResults.write('\n');
}
available= tidyReader.ready();
}
}
available= tidyReader.ready();
if (! available && ! isAlive(process))
break;
}
fTidyResults.flush();
try {
return process.exitValue() == 0;
} catch (IllegalThreadStateException e) {
process.destroy();
fail("'" + command + "' killed after " + TIDY_TIMEOUT +" ms");
return false;
}
}
private static boolean isRelevant(String line) {
return ! EXCLUSION_PATTERN_TABLE_SUMMARY.matcher(line).matches()
&& ! EXCLUSION_PATTERN_EMPTY_TAG.matcher(line).matches()
&& ! EXCLUSION_PATTERN_MALFORMED_URI.matcher(line).matches()
&& ! eXCLUSION_PATTERN_SCRIPT_TYPE.matcher(line).matches()
&& ! eXCLUSION_PATTERN_IMG_LACKS_ALT.matcher(line).matches()
;
}
private static boolean isAlive(Process process) {
try {
process.exitValue();
} catch (IllegalThreadStateException e) {
return true;
}
return false;
}
private static boolean isHTMLFile(File file) {
String name= file.getName();
return (name.endsWith(".html") || name.endsWith(".htm")) && file.isFile();
}
}