more tests

This commit is contained in:
snafu 2013-12-07 12:50:04 +01:00
parent ba53b67ccf
commit 766da3d665
22 changed files with 961 additions and 0 deletions

5
.gitignore vendored Normal file
View file

@ -0,0 +1,5 @@
.classpath
.project
.settings
*~
target

View file

@ -0,0 +1,14 @@
package yooze;
@SuppressWarnings("serial")
public class ClassNotFound extends RuntimeException {
public ClassNotFound(String message) {
super(message);
}
public ClassNotFound(Throwable cause) {
super(cause);
}
}

View file

@ -0,0 +1,11 @@
package yooze;
import java.util.List;
import javassist.ClassPath;
public interface InspectableClasspath extends ClassPath {
public String getResourceName();
public List<String> getClasses();
}

View file

@ -0,0 +1,11 @@
package yooze;
import java.io.File;
import java.io.IOException;
import java.util.List;
public interface Scanner {
public List<InspectableClasspath> scanArchive(String archiveName) throws IOException;
public List<InspectableClasspath> scanArchive(File file) throws IOException;
}

View file

@ -0,0 +1,40 @@
package yooze.application;
import yooze.GraphBuilder;
import yooze.scanner.ArchiveScanner;
import yooze.scanner.ClassesDirScanner;
import yooze.scanner.LibScanner;
import yooze.scanner.TgzScanner;
import yooze.scanner.WarScanner;
public class GraphBuilderFactory {
/**
* Factory method for getting a builder that does earfiles
*/
public static GraphBuilder getEarBuilder() {
return new GraphBuilder(new ArchiveScanner(new WarScanner()));
}
/**
* Factory method for getting a builder that does (downloaded) .tar.gz files
*/
public static GraphBuilder getDefaultTgzBuilder() {
GraphBuilder tgzBuilder = new GraphBuilder(new TgzScanner());
tgzBuilder.setPackageExcludePatterns("java.*", "sun.*", "com.sun.*");
return tgzBuilder;
}
/**
* Factory method for getting a builder that scans a lib directory (containing jars)
*/
public static GraphBuilder getLibDirectoryBuilder() {
return new GraphBuilder(new LibScanner());
}
/**
* Factory method for getting a builder that scans a directory containing classes
*/
public static GraphBuilder getClassesDirectoryBuilder() {
return new GraphBuilder(new ClassesDirScanner());
}
}

View file

@ -0,0 +1,89 @@
package yooze.application;
import java.util.concurrent.ConcurrentHashMap;
import org.neo4j.graphdb.Direction;
import org.neo4j.graphdb.GraphDatabaseService;
import org.neo4j.graphdb.Node;
import org.neo4j.graphdb.RelationshipType;
import org.neo4j.graphdb.ReturnableEvaluator;
import org.neo4j.graphdb.StopEvaluator;
import org.neo4j.graphdb.Transaction;
import org.neo4j.graphdb.Traverser;
import org.neo4j.kernel.EmbeddedGraphDatabase;
import yooze.domain.ClassModel;
public class Neo4jDao {
private GraphDatabaseService graphDb;
private Node rootNode;
private ConcurrentHashMap<String, Node> nodes = new ConcurrentHashMap<String, Node>();
public enum MyRelationshipTypes implements RelationshipType {
CONTAINS, REFERENCES
}
public Neo4jDao(String database) {
graphDb = new EmbeddedGraphDatabase(database);
Transaction tx = graphDb.beginTx();
try {
rootNode = graphDb.createNode();
rootNode.setProperty("name", "root");
tx.success();
} finally {
tx.finish();
}
}
public void insertClass(ClassModel classModel) {
Transaction tx = graphDb.beginTx();
try {
Node newNode = findOrCreateNode(classModel);
for (ClassModel ref : classModel.getReferences()) {
Node refNode = findOrCreateNode(ref);
newNode.createRelationshipTo(refNode,
MyRelationshipTypes.REFERENCES);
}
tx.success();
} finally {
tx.finish();
}
}
private Node findOrCreateNode(ClassModel classModel) {
Node newNode = findNode(classModel.getName());
if (newNode == null) {
Transaction tx = graphDb.beginTx();
try {
newNode = graphDb.createNode();
newNode.setProperty("name", classModel.getName());
tx.success();
} finally {
tx.finish();
}
}
return newNode;
}
public Node findNode(String className) {
Node node = nodes.get(className);
if (node != null) {
return node;
}
// do "tablescan". is there a better way?
Traverser classesTraverser = rootNode.traverse(
Traverser.Order.BREADTH_FIRST, StopEvaluator.DEPTH_ONE,
ReturnableEvaluator.ALL_BUT_START_NODE,
MyRelationshipTypes.CONTAINS, Direction.OUTGOING);
for (Node nextNode : classesTraverser) {
if (nextNode.getProperty("name").equals(className)) {
nodes.put(className, nextNode);
return nextNode;
}
}
return null;// not found
}
}

View file

@ -0,0 +1,41 @@
package yooze.application;
import java.io.IOException;
import yooze.GraphBuilder;
import yooze.domain.ClassModel;
import yooze.domain.Graph;
public class Yooze {
private String neo4jDb;
public static void main(String[] args) throws IOException {
String neoDb = args[0];
String earfile = args[1];
String in = args[2];
String ex = args[2];
String startingClassname = args[3];
new Yooze(neoDb).createNeoGraph(earfile, in, ex, startingClassname);
}
public Yooze(String neo4jDb) {
super();
this.neo4jDb = neo4jDb;
}
public void createNeoGraph(String archive, String packageIncludePatterns, String packageExcludePatterns,
String startingClass) throws IOException {
GraphBuilder libDirectoryBuilder = GraphBuilderFactory.getLibDirectoryBuilder();
libDirectoryBuilder.setPackageExcludePatterns(packageExcludePatterns);
libDirectoryBuilder.setPackageIncludePatterns(packageIncludePatterns);
Graph graph = libDirectoryBuilder.build(archive, startingClass);
Neo4jDao neo4jDao = new Neo4jDao(neo4jDb);
for (ClassModel model : graph.getChildren()) {
neo4jDao.insertClass(model);
}
}
}

View file

@ -0,0 +1,14 @@
package yooze.domain;
@SuppressWarnings("serial")
public class MethodNotFound extends RuntimeException {
public MethodNotFound(String message) {
super(message);
}
public MethodNotFound(Throwable cause) {
super(cause);
}
}

View file

@ -0,0 +1,49 @@
package yooze.output;
import java.io.OutputStream;
import yooze.Statistics;
import yooze.domain.ClassModel;
import yooze.domain.Graph;
/**
* prints the graph as a graphviz dot file. Takes care of circular dependencies. Not threadsafe.
*/
public class DotPrinter extends GraphPrinter {
public DotPrinter(OutputStream out) {
super(out);
}
public void print(Graph g) {
println("digraph \"" + g.getName() + "\" {");
println("graph [size=100,100];");
for (ClassModel cm : g.getChildren()) {
printClassModel(cm);
}
println("}");
}
private void printClassModel(ClassModel cm) {
double boxsize = Math.sqrt(Statistics.getByteCodeSizeForClass(cm.getName()));
print("\"");
print(cm.getName());
println("\" [shape=box, height=" + boxsize / 20 + "];");
if (cm.getReferences() == null || cm.getReferences().size() == 0) {
print("\"");
print(cm.getName());
println("\";");
} else {
for (ClassModel ref : cm.getReferences()) {
String relation = String.format("\"%s\" -> \"%s\"", cm.getName(), ref.getName());
if (shouldPrint(relation)) {
println(relation);
markAsPrinted(relation);
printClassModel(ref); // recurse
}
}
}
}
}

View file

@ -0,0 +1,38 @@
package yooze.output;
import java.io.OutputStream;
import java.io.PrintStream;
import java.util.ArrayList;
import yooze.domain.Graph;
/**
* Facilitates subclasses to take care of circular dependencies, using shouldPrint and markAsPrinted
*
*/
public abstract class GraphPrinter extends PrintStream {
private ArrayList<String> printedRelations;
public GraphPrinter(OutputStream out) {
super(out);
printedRelations = new ArrayList<String>();
}
abstract public void print(Graph g);
protected boolean shouldPrint(String relation) {
return !printedRelations.contains(relation);
}
protected void markAsPrinted(String relation) {
printedRelations.add(relation);
}
@SuppressWarnings("serial")
protected static class CouldNotPrint extends RuntimeException {
public CouldNotPrint(Throwable t) {
super(t);
}
}
}

View file

@ -0,0 +1,34 @@
package yooze.output;
import java.io.OutputStream;
import yooze.domain.ClassModel;
import yooze.domain.Graph;
public class JsonPrinter extends GraphPrinter {
public JsonPrinter(OutputStream out) {
super(out);
}
@Override
public void print(Graph g) {
print("[");
for (ClassModel cm : g.getChildren()) {
printClassModel(cm);
}
print("]");
}
private void printClassModel(ClassModel cm) {
for (ClassModel ref : cm.getReferences()) {
String relation = String.format("{\"key\":\"%s\",\"parent\":\"%s\"},", ref.getName(), cm.getName());
if (shouldPrint(relation)) {
print(relation);
markAsPrinted(relation);
printClassModel(ref); // recurse
}
}
}
}

View file

@ -0,0 +1,28 @@
package yooze.scanner;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import yooze.InspectableClasspath;
import yooze.Scanner;
/**
* reads classes as .class files from a directory
*/
public class ClassesDirScanner implements Scanner {
@Override
public List<InspectableClasspath> scanArchive(String archiveName) throws IOException {
return scanArchive(new File(archiveName));
}
@Override
public List<InspectableClasspath> scanArchive(File file) throws IOException {
List<InspectableClasspath> result = new ArrayList<InspectableClasspath>();
result.add(new DirClassPath(file));
return result;
}
}

View file

@ -0,0 +1,18 @@
package yooze.scanner;
import java.io.File;
import java.io.IOException;
import java.util.List;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;
import yooze.InspectableClasspath;
import yooze.Util;
public class ClasspathAdder {
public static void addEntriesFromWarToClasspath(JarFile warfile, List<InspectableClasspath> classpaths,
JarEntry entry) throws IOException {
File jarFile = Util.extractFile(warfile, entry);
classpaths.add(new JarClassPath(new JarFile(jarFile)));
}
}

View file

@ -0,0 +1,90 @@
package yooze.scanner;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;
import javassist.NotFoundException;
import yooze.ClassByteCountingInputStream;
import yooze.ClassNotFound;
import yooze.InspectableClasspath;
import yooze.Util;
public class DirClassPath implements InspectableClasspath {
private final File dir;
public DirClassPath(File dir) {
super();
this.dir = dir;
}
public void close() {
}
public URL find(String className) {
try {
return new URL("file:///" + dir.getCanonicalPath() + "/" + Util.toClassResource(className));
} catch (IOException e) {
throw new ClassNotFound(e);
}
}
@Override
public String toString() {
return "DirectoryClasspath[" + dir + "]";
}
public List<String> getClasses() {
List<String> classes = new ArrayList<String>();
getClasses(dir, dir, classes);
return classes;
}
private void getClasses(File root, File dir, List<String> classes) {
File[] fileList = dir.listFiles();
for (File entry : fileList) {
if (entry.isDirectory()) {
// recurse deeper
getClasses(root, entry, classes);
} else if (isClassFile(entry)) {
classes.add(createQualifiedClassNameFromFileLocation(root, entry));
}
}
}
private boolean isClassFile(File entry) {
return entry.isFile() && entry.getName().endsWith(".class");
}
private String createQualifiedClassNameFromFileLocation(File root, File classFile) {
String absolutePath = classFile.getAbsolutePath();
String relativePath = absolutePath.substring(root.getAbsolutePath().length() + 1);
String packageFormat = relativePath.replaceAll("\\\\", ".").replaceAll("/", ".");
String substring = packageFormat.substring(0, packageFormat.length() - 6);
return substring;
}
@Override
public String getResourceName() {
return dir.getName();
}
@Override
public InputStream openClassfile(String className) throws NotFoundException {
File classFile = new File(dir, Util.toClassResource(className) + ".class");
if (!classFile.exists()) {
return null;
}
try {
return new ClassByteCountingInputStream(className, new FileInputStream(classFile));
} catch (FileNotFoundException e) {
throw new RuntimeException(e);
}
}
}

View file

@ -0,0 +1,78 @@
package yooze.scanner;
import java.io.IOException;
import java.io.InputStream;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.List;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;
import java.util.zip.ZipEntry;
import javassist.NotFoundException;
import yooze.ClassByteCountingInputStream;
import yooze.ClassNotFound;
import yooze.InspectableClasspath;
import yooze.Util;
public class JarClassPath implements InspectableClasspath {
private final JarFile jar;
public JarClassPath(JarFile jar) {
super();
this.jar = jar;
}
public void close() {
try {
jar.close();
} catch (IOException e) {
throw new RuntimeException(e);
}
}
public URL find(String className) {
try {
return new URL("file:///" + jar.getName() + "!" + Util.toClassResource(className));
} catch (MalformedURLException e) {
throw new RuntimeException(e);
}
}
@Override
public String toString() {
return "JarClasspath[" + jar.getName() + "]";
}
public List<String> getClasses() {
List<String> classes = new ArrayList<String>();
for (Enumeration<JarEntry> entries = jar.entries(); entries.hasMoreElements();) {
String name = entries.nextElement().getName().replaceAll("/", ".");
if (name.endsWith(".class")) {
classes.add(name.substring(0, name.length() - 6));
}
}
return classes;
}
public String getResourceName() {
return jar.getName();
}
@Override
public InputStream openClassfile(String className) throws NotFoundException {
ZipEntry entry = jar.getEntry(Util.toClassResource(className));
if (entry == null) {
throw new ClassNotFound(className);
}
try {
return new ClassByteCountingInputStream(className, jar.getInputStream(entry));
} catch (IOException e) {
throw new RuntimeException(e);
}
}
}

View file

@ -0,0 +1,108 @@
package yooze.scanner;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.List;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.zip.ZipEntry;
import org.apache.commons.io.IOUtils;
import yooze.InspectableClasspath;
public class WarScanner {
private final static Pattern classPattern = Pattern.compile("WEB-INF/classes/(.*)\\.class");
private final static Pattern packagePattern = Pattern.compile("(.+\\/+)(.+\\.class)");
public List<InspectableClasspath> scanWars(List<JarFile> wars) {
List<InspectableClasspath> classpaths = new ArrayList<InspectableClasspath>();
for (JarFile war : wars) {
classpaths.addAll(scanWar(war));
}
return classpaths;
}
private List<InspectableClasspath> scanWar(JarFile warfile) {
List<InspectableClasspath> classpaths = new ArrayList<InspectableClasspath>();
File classesDir = createTempLocation(classpaths);
classpaths.add(new DirClassPath(classesDir));
for (Enumeration<JarEntry> entries = warfile.entries(); entries.hasMoreElements();) {
JarEntry entry = (JarEntry) entries.nextElement();
if (isArchive(entry)) {
try {
ClasspathAdder.addEntriesFromWarToClasspath(warfile, classpaths, entry);
} catch (IOException e) {
throw new RuntimeException(e);
}
} else {
extractClass(warfile, entry, classesDir);
}
}
return classpaths;
}
private File createTempLocation(List<InspectableClasspath> classpaths) {
File classesDir = new File(new File(System.getProperty("java.io.tmpdir")), "classes"
+ System.currentTimeMillis());
boolean dirsMade = classesDir.mkdirs();
if (!dirsMade) {
throw new RuntimeException("Directory " + classesDir + " could not be created");
}
return classesDir;
}
private boolean isArchive(JarEntry entry) {
String name = entry.getName();
return name.startsWith("WEB-INF/lib") && name.endsWith(".jar");
}
private File extractClass(JarFile warfile, ZipEntry entry, File classesDir) {
Matcher matcher = classPattern.matcher(entry.getName());
if (matcher.matches()) {
String className = matcher.group(1) + ".class";
Matcher matcher2 = packagePattern.matcher(className);
if (matcher2.matches()) {
String packageName = matcher2.group(1);
File classDir = createUnarchivedPackageDicectory(classesDir, packageName);
String simpleClassName = matcher2.group(2);
File classFile = new File(classDir, simpleClassName);
return createUnarchivedClassfile(warfile, entry, classFile);
}
}
return null;
}
private File createUnarchivedClassfile(JarFile warfile, ZipEntry entry, File classFile) {
try {
FileOutputStream out = new FileOutputStream(classFile);
IOUtils.copy(warfile.getInputStream(entry), out);
return classFile;
} catch (IOException e) {
throw new RuntimeException(e);
}
}
private File createUnarchivedPackageDicectory(File classesDir, String packageName) {
File classDir = new File(classesDir, packageName);
if (!classDir.exists()) {
boolean packageDirsMade = classDir.mkdirs();
if (!packageDirsMade) {
throw new DirectoryCouldNotBeCreated(classDir);
}
}
return classDir;
}
private static class DirectoryCouldNotBeCreated extends RuntimeException {
public DirectoryCouldNotBeCreated(File classDir) {
super(classDir.toString());
}
}
}

86
src/main/resources/go.js Normal file
View file

@ -0,0 +1,86 @@
function init(){
var $ = go.GraphObject.make; // for conciseness in defining templates
var diagram = $(go.Diagram, "myDiagram"); //
// Define a node template showing class names.
// Double-clicking opens up the documentation for that class.
diagram.nodeTemplate =
$(go.Node, "Auto",
{ doubleClick: nodeDoubleClick }, // this function is defined below
{ toolTip:
$(go.Adornment, "Auto",
$(go.Shape, { fill: "lightyellow" }),
$(go.TextBlock, "double-click\nfor documentation",
{ margin: 5 })
)
},
$(go.Shape, { fill: "darkslategray", stroke: null }),
$(go.TextBlock,
{ font: "bold 13px Helvetica, bold Arial, sans-serif",
stroke: "white", margin: 3 },
new go.Binding("text", "key")));
// Define a trivial link template with no arrowhead
diagram.linkTemplate =
$(go.Link, // the whole link panel
{ selectable: false },
$(go.Shape)); // the link shape, with the default black stroke
// Collect all of the data for the model of the class hierarchy
var nodeDataArray = [];
// Iterate over all of the classes in "go"
for (k in go) {
var cls = go[k];
if (!cls) continue;
var proto = cls.prototype;
if (!proto) continue;
proto.constructor.className = k; // remember name
// find base class constructor
var base = Object.getPrototypeOf(cls.prototype).constructor;
if (base === Object) { // "root" node?
nodeDataArray.push({ key: k });
} else {
// add a node for this class and a tree-parent reference to the base class name
nodeDataArray.push({ key: k, parent: base.className });
}
}
// Create the model for the hierarchy diagram
diagram.model = new go.TreeModel(nodeDataArray);
// Now collect all node data that are singletons
var singlesArray = []; // for classes that don't inherit from another class
var it = diagram.nodes;
while (it.next()) {
var node = it.value;
if (node.linksConnected.count === 0) {
singlesArray.push(node.data);
}
}
// Remove the unconnected class nodes from the main Diagram
for (var i = 0; i < singlesArray.length; i++) {
diagram.model.removeNodeData(singlesArray[i]);
}
// Now lay out the diagram as a tree;
// separate trees are arranged vertically above each other.
diagram.layout = $(go.TreeLayout, { nodeSpacing: 3 });
// Display the unconnected classes in a separate Diagram
var singletons =
$(go.Diagram, "mySingletons",
{ nodeTemplate: diagram.nodeTemplate, // Share the node template with the main Diagram
layout:
$(go.GridLayout,
{ wrappingColumn: 1, // Put the unconnected nodes in a column
spacing: new go.Size(3, 3) }),
model: new go.Model(singlesArray) }); // Use a separate model
}
// When a Node is double clicked, open the documentation for the corresponding class in a new window
function nodeDoubleClick(event, node) {
window.open("../api/symbols/" + node.data.key + ".html");
}

View file

@ -0,0 +1,72 @@
package yooze.output;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import junit.framework.Assert;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import yooze.ClassCache;
import yooze.GraphBuilder;
import yooze.application.GraphBuilderFactory;
import yooze.domain.Graph;
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = "classpath:applicationContext-test.xml")
public class DotPrinterTest {
@Before
public void clearClassCache() {
ClassCache.clear();
}
@Test
public void dotPrinting() throws IOException {
GraphBuilder directoryBuilder = GraphBuilderFactory.getClassesDirectoryBuilder();
directoryBuilder.setPackageExcludePatterns(".*?Class4");
directoryBuilder.setPackageIncludePatterns(".*?.Class.");
Graph graph = directoryBuilder.build("target/test-classes", "yooze.Class1");
ByteArrayOutputStream bytes = new ByteArrayOutputStream(500);
DotPrinter d = new DotPrinter(bytes);
d.print(graph);
String dotText = new String(bytes.toByteArray());
d.close();
String[] expectedDotTextLines = { "digraph \"test-classes\" {", "graph [size=100,100];",
"\"yooze.Class1\" [shape=box, height=0.0];", "\"yooze.Class1\" -> \"yooze.Class2\"",
"\"yooze.Class2\" [shape=box, height=0.0];", "\"yooze.Class2\" -> \"yooze.Class3\"",
"\"yooze.Class3\" [shape=box, height=0.0];", "\"yooze.Class3\" -> \"yooze.Class1\"",
"\"yooze.Class1\" [shape=box, height=0.0];", "\"yooze.Class2\" [shape=box, height=0.0];",
"\"yooze.Class3\" [shape=box, height=0.0];", "}" };
System.out.println(dotText);
expectTextContainsLines(dotText, expectedDotTextLines);
}
private void expectTextContainsLines(String dotText, String[] expectedDotTextLines) {
for (String line : expectedDotTextLines) {
Assert.assertTrue("Not found:" + line, dotText.contains(line));
}
}
@Test
public void noReference() throws IOException {
GraphBuilder directoryBuilder = GraphBuilderFactory.getClassesDirectoryBuilder();
directoryBuilder.setPackageExcludePatterns("");
directoryBuilder.setPackageIncludePatterns("yooze.Class4");
Graph graph = directoryBuilder.build("target/test-classes", "yooze.Class4");
ByteArrayOutputStream bytes = new ByteArrayOutputStream(1000);
DotPrinter d = new DotPrinter(bytes);
d.print(graph);
String dotText = new String(bytes.toByteArray());
System.out.println(dotText);
String[] expectedDotTextLines = { "digraph \"test-classes\" {", "graph [size=100,100];",
"\"yooze.Class4\" [shape=box, height=0.0];", "\"yooze.Class4\";", "}" };
d.close();
expectTextContainsLines(dotText, expectedDotTextLines);
}
}

View file

@ -0,0 +1,38 @@
package yooze.output;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import junit.framework.Assert;
import org.junit.Before;
import org.junit.Test;
import yooze.ClassCache;
import yooze.GraphBuilder;
import yooze.application.GraphBuilderFactory;
import yooze.domain.Graph;
public class JsonPrinterTest {
@Before
public void clearClassCache() {
ClassCache.clear();
}
@Test
public void jsonShouldBeWellFormed() throws IOException {
GraphBuilder directoryBuilder = GraphBuilderFactory.getClassesDirectoryBuilder();
directoryBuilder.setPackageExcludePatterns(".*?Class4");
directoryBuilder.setPackageIncludePatterns(".*?.Class.");
Graph graph = directoryBuilder.build("target/test-classes", "yooze.Class1");
ByteArrayOutputStream bytes = new ByteArrayOutputStream(500);
GraphPrinter d = new JsonPrinter(bytes);
d.print(graph);
String json = new String(bytes.toByteArray());
d.close();
Assert.assertEquals(
"[{\"key\":\"yooze.Class2\",\"parent\":\"yooze.Class1\"},{\"key\":\"yooze.Class3\",\"parent\":\"yooze.Class2\"},{\"key\":\"yooze.Class1\""
+ ",\"parent\":\"yooze.Class3\"},]", json);
}
}

View file

@ -0,0 +1,30 @@
package yooze.scanner;
import java.util.List;
import org.junit.Before;
import org.junit.Test;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import yooze.InspectableClasspath;
public class ArchiveScannerTest {
@InjectMocks
private ArchiveScanner archiveScanner;
@Mock
private WarScanner warScanner;
@Before
public void createArchiveScanner() {
MockitoAnnotations.initMocks(this);
}
@Test
public void nothing() {
List<InspectableClasspath> scanArchive = archiveScanner.scanArchive(".");
}
}

View file

@ -0,0 +1,48 @@
package yooze.scanner;
import static org.hamcrest.core.Is.is;
import static org.junit.Assert.assertThat;
import static org.junit.Assert.assertTrue;
import java.io.IOException;
import java.util.List;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import yooze.Config;
import yooze.InspectableClasspath;
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = "classpath:applicationContext-test.xml")
public class EarScannerTest {
@Autowired
private Config config;
@Test
public void scanner() throws IOException {
List<InspectableClasspath> classpaths = new ArchiveScanner(new WarScanner()).scanArchive(config.getEarFile());
for (InspectableClasspath path : classpaths) {
if (path instanceof DirClassPath) {
List<String> classes = ((InspectableClasspath) path).getClasses();
assertThat(classes.size(), is(49));
}
if (path instanceof JarClassPath) {
String name = ((InspectableClasspath) path).getResourceName();
if (name.contains("standard")) {
List<String> classes = ((InspectableClasspath) path).getClasses();
assertTrue(classes.contains("org.apache.taglibs.standard.tag.common.sql.DataSourceUtil"));
}
}
}
}
public void setConfig(Config config) {
this.config = config;
}
}

View file

@ -0,0 +1,19 @@
package yooze.scanner;
import static junit.framework.Assert.assertTrue;
import java.io.IOException;
import java.util.List;
import org.junit.Test;
import yooze.InspectableClasspath;
public class LibScannerTest {
@Test
public void directoryWithoutJars_isNotAClasspathEntry() throws IOException {
LibScanner libScanner = new LibScanner();
List<InspectableClasspath> classpathList = libScanner.scanArchive("src");
assertTrue("This should be empty", classpathList.isEmpty());
}
}