Initial revision

This commit is contained in:
Diomidis Spinellis 2005-11-14 17:40:14 +00:00
parent dac09f0720
commit 5da7e8c305
4 changed files with 806 additions and 0 deletions

View File

@ -0,0 +1,95 @@
/*
* UmlGraph class diagram testing framework
*
* Contibuted by Andrea Aime
* (C) Copyright 2005 Diomidis Spinellis
*
* Permission to use, copy, and distribute this software and its
* documentation for any purpose and without fee is hereby granted,
* provided that the above copyright notice appear in all copies and that
* both that copyright notice and this permission notice appear in
* supporting documentation.
*
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
* MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
*
* $Id$
*
*/
package gr.spinellis.umlgraph.test;
import java.io.File;
import java.io.FilenameFilter;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.List;
public class BasicTest {
static String testSourceFolder = "./test-data/simple/java";
static String testDestFolder = "./test-data/simple/dot-out";
static String testRefFolder = "./test-data/simple/dot-ref";
static PrintWriter pw = new PrintWriter(System.out);
public static void main(String[] args) throws IOException {
String[] javaFiles = new File(testSourceFolder).list(new JavaFilter());
// String[] javaFiles = new String[] {"MyVector.java"};
File outFolder = new File(testDestFolder);
if (!outFolder.exists())
outFolder.mkdirs();
boolean equal = true;
for (int i = 0; i < javaFiles.length; i++) {
String javaFileName = javaFiles[i].substring(0, javaFiles[i].length() - 5);
String dotPath = new File(testDestFolder, javaFileName + ".dot").getAbsolutePath();
String refPath = new File(testRefFolder, javaFileName + ".dot").getAbsolutePath();
String javaPath = new File(testSourceFolder, javaFiles[i]).getAbsolutePath();
String[] options = new String[] { "-hide", "Hidden", "-private", "-output", dotPath,
javaPath };
com.sun.tools.javadoc.Main.execute("UMLGraph test", pw, pw, pw, "UmlGraph", options);
System.out.println("Performing diff:\nout:" + dotPath + "\nref:" + refPath);
DotDiff differ = new DotDiff(new File(dotPath), new File(refPath));
if (differ.graphEquals()) {
System.out.println("File contents are structurally equal");
} else {
equal = false;
System.out.println("File contents are structurally not equal");
printList("# Lines in out but not in ref", differ.getExtraLines1());
printList("# Lines in ref but not in out", differ.getExtraLines2());
printList("# Nodes in out but not in ref", differ.getNodes1());
printList("# Nodes in ref but not in out", differ.getNodes2());
printList("# Arcs in out but not in ref", differ.getArcs1());
printList("# Arcs in ref but not in out", differ.getArcs2());
}
System.out.println("\n\n");
}
if (!equal)
System.out.println("ERROR, some file are not structurally equal");
else
System.out.println("GOOD, all files are structurally equal");
}
private static void printList(String message, List extraOut) {
if (extraOut.size() > 0) {
System.out.println(message);
for (Object o : extraOut) {
System.out.println(o);
}
}
}
private static final class JavaFilter implements FilenameFilter {
public boolean accept(File dir, String name) {
return name.endsWith(".java");
}
}
}

View File

@ -0,0 +1,308 @@
/*
* UmlGraph class diagram testing framework
*
* Contibuted by Andrea Aime
* (C) Copyright 2005 Diomidis Spinellis
*
* Permission to use, copy, and distribute this software and its
* documentation for any purpose and without fee is hereby granted,
* provided that the above copyright notice appear in all copies and that
* both that copyright notice and this permission notice appear in
* supporting documentation.
*
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
* MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
*
* $Id$
*
*/
package gr.spinellis.umlgraph.test;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.io.StreamTokenizer;
import java.io.StringReader;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
public class DotDiff {
private List<DotNode> nodes1 = new ArrayList<DotNode>();
private List<DotNode> nodes2 = new ArrayList<DotNode>();
private List<DotArc> arcs1 = new ArrayList<DotArc>();
private List<DotArc> arcs2 = new ArrayList<DotArc>();
private List<String> extraLines1 = new ArrayList<String>();
private List<String> extraLines2 = new ArrayList<String>();
/**
* Builds a dot differ on the two files
*
* @param dotFirst
* @param dotSecond
* @throws IOException
*/
public DotDiff(File dotFirst, File dotSecond) throws IOException {
// gather the lines
List<String> lines1 = readGraphLines(dotFirst);
List<String> lines2 = readGraphLines(dotSecond);
// parse the lines
extraLines1 = parseLines(lines1, nodes1, arcs1);
extraLines2 = parseLines(lines2, nodes2, arcs2);
// diff extra lines
for (Iterator<String> it = extraLines1.iterator(); it.hasNext();) {
if (extraLines2.remove(it.next()))
it.remove();
}
// diff nodes
for (Iterator<DotNode> it = nodes1.iterator(); it.hasNext();) {
if (nodes2.remove(it.next()))
it.remove();
}
// diff arcs
for (Iterator<DotArc> it = arcs1.iterator(); it.hasNext();) {
if (arcs2.remove(it.next()))
it.remove();
}
}
/**
* Returns true if the dot files are structurally equal, that is, if every
* non comment and non header line of the first file appears in the second,
* and otherwise.
*
* @return
*/
public boolean graphEquals() {
return (extraLines1.size() + extraLines2.size() + nodes1.size() + nodes2.size()
+ arcs1.size() + arcs2.size()) == 0;
}
public List<DotArc> getArcs1() {
return arcs1;
}
public List<DotArc> getArcs2() {
return arcs2;
}
public List<String> getExtraLines1() {
return extraLines1;
}
public List<String> getExtraLines2() {
return extraLines2;
}
public List<DotNode> getNodes1() {
return nodes1;
}
public List<DotNode> getNodes2() {
return nodes2;
}
/**
* Reads all relevant lines from the dot file
*
* @param dotFile
* @return
* @throws IOException
*/
private List<String> readGraphLines(File dotFile) throws IOException {
List<String> lines = new ArrayList<String>();
BufferedReader br = null;
try {
br = new BufferedReader(new FileReader(dotFile));
String line;
while ((line = br.readLine()) != null) {
line = line.trim();
if (graphDefinitionLine(line))
lines.add(line);
}
} finally {
if (br != null)
br.close();
}
return lines;
}
/**
* Tells if a line is relevant or not (unrelevant lines are headers,
* comments, "digraf G {" and the closing "}" (to simplify matters we assume
* the file is properly structured).
*
* @param line
* @return
*/
private boolean graphDefinitionLine(String line) {
return !(line.startsWith("#") || line.startsWith("//") || line.equals("digraph G {") || line
.equals("}"));
}
private List<String> parseLines(List<String> lines, List<DotNode> nodeList, List<DotArc> arcs)
throws IOException {
List<String> extraLines = new ArrayList<String>();
List<String> arcLines = new ArrayList<String>();
Map<String, DotNode> nodes = new HashMap<String, DotNode>();
for (String line : lines) {
int openBrackedIdx = line.indexOf('[');
int closedBracketIdx = line.lastIndexOf(']');
int arrowIdx = line.indexOf("->");
if (openBrackedIdx < 0 && closedBracketIdx < 0 || line.startsWith("edge")
|| line.startsWith("node"))
extraLines.add(line);
else if (arrowIdx > 0 && arrowIdx < openBrackedIdx) { // that's an
arcLines.add(line);
} else { // that's a node
String attributes = line.substring(openBrackedIdx + 1, closedBracketIdx);
Map<String, String> attMap = parseAttributes(attributes);
String name = line.substring(0, openBrackedIdx - 1).trim();
String label = attMap.get("label");
DotNode node = new DotNode(name, label, attMap, line);
nodes.put(name, node);
nodeList.add(node);
}
}
for (String line : arcLines) {
int openBrackedIdx = line.indexOf('[');
int closedBracketIdx = line.lastIndexOf(']');
String attributes = line.substring(openBrackedIdx + 1, closedBracketIdx);
String[] names = line.substring(0, openBrackedIdx).split("->");
DotNode from = nodes.get(names[0].trim());
DotNode to = nodes.get(names[1].trim());
if (from == null) {
from = new DotNode(names[0], "", new HashMap<String, String>(), "");
}
if (to == null) {
to = new DotNode(names[1], "", new HashMap<String, String>(), "");
}
arcs.add(new DotArc(from, to, parseAttributes(attributes), line));
}
return extraLines;
}
private Map<String, String> parseAttributes(String attributes) throws IOException {
Map<String, String> map = new HashMap<String, String>();
StreamTokenizer st = new StreamTokenizer(new StringReader(attributes));
st.wordChars('_', '_');
st.wordChars('\\', '\\');
st.wordChars('\'', '\'');
int tokenType;
boolean isValue = false;
String attName = null;
String token = null;
while ((tokenType = st.nextToken()) != StreamTokenizer.TT_EOF) {
switch (tokenType) {
case StreamTokenizer.TT_NUMBER:
token = "" + st.nval;
break;
case StreamTokenizer.TT_WORD:
case '"':
case '\'':
token = st.sval;
break;
}
tokenType = st.nextToken();
if (isValue) {
map.put(attName, token);
isValue = false;
} else {
attName = token;
isValue = true;
}
}
return map;
}
private static class DotNode {
String name;
String label;
Map<String, String> attributes;
String line;
public DotNode(String name, String label, Map<String, String> attributes, String line) {
this.name = name;
this.label = label.replace("\n", "\\n");
this.attributes = attributes;
this.line = line.replace("\n", "\\n");
}
public boolean equals(Object other) {
if (!(other instanceof DotNode))
return false;
DotNode on = (DotNode) other;
if (label == null) // anonymous node
return on.label == null && on.name.equals(name) && on.attributes.equals(attributes);
else
return on.label.equals(label) && on.attributes.equals(attributes);
}
public int hashCode() {
return name.hashCode() + 17 * attributes.hashCode();
}
public String toString() {
return "Node: " + label + "; " + line;
}
}
private static class DotArc {
DotNode from;
DotNode to;
Map<String, String> attributes;
String line;
public DotArc(DotNode from, DotNode to, Map<String, String> attributes, String line) {
this.from = from;
this.to = to;
this.attributes = attributes;
this.line = line.replace("\n", "\\n");
}
public boolean equals(Object other) {
if (!(other instanceof DotArc))
return false;
DotArc oa = (DotArc) other;
return oa.from.equals(from) && oa.to.equals(to) && oa.attributes.equals(attributes);
}
public int hashCode() {
return from.hashCode() + 17 * (to.hashCode() + 17 * attributes.hashCode());
}
public String toString() {
return "Arc: " + from.label + " -> " + to.label + "; " + line;
}
}
}

View File

@ -0,0 +1,95 @@
/*
* UmlGraph class diagram testing framework
*
* Contibuted by Andrea Aime
* (C) Copyright 2005 Diomidis Spinellis
*
* Permission to use, copy, and distribute this software and its
* documentation for any purpose and without fee is hereby granted,
* provided that the above copyright notice appear in all copies and that
* both that copyright notice and this permission notice appear in
* supporting documentation.
*
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
* MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
*
* $Id$
*
*/
package gr.spinellis.umlgraph.test;
import java.io.File;
import java.io.FilenameFilter;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.List;
public class BasicTest {
static String testSourceFolder = "./test-data/simple/java";
static String testDestFolder = "./test-data/simple/dot-out";
static String testRefFolder = "./test-data/simple/dot-ref";
static PrintWriter pw = new PrintWriter(System.out);
public static void main(String[] args) throws IOException {
String[] javaFiles = new File(testSourceFolder).list(new JavaFilter());
// String[] javaFiles = new String[] {"MyVector.java"};
File outFolder = new File(testDestFolder);
if (!outFolder.exists())
outFolder.mkdirs();
boolean equal = true;
for (int i = 0; i < javaFiles.length; i++) {
String javaFileName = javaFiles[i].substring(0, javaFiles[i].length() - 5);
String dotPath = new File(testDestFolder, javaFileName + ".dot").getAbsolutePath();
String refPath = new File(testRefFolder, javaFileName + ".dot").getAbsolutePath();
String javaPath = new File(testSourceFolder, javaFiles[i]).getAbsolutePath();
String[] options = new String[] { "-hide", "Hidden", "-private", "-output", dotPath,
javaPath };
com.sun.tools.javadoc.Main.execute("UMLGraph test", pw, pw, pw, "UmlGraph", options);
System.out.println("Performing diff:\nout:" + dotPath + "\nref:" + refPath);
DotDiff differ = new DotDiff(new File(dotPath), new File(refPath));
if (differ.graphEquals()) {
System.out.println("File contents are structurally equal");
} else {
equal = false;
System.out.println("File contents are structurally not equal");
printList("# Lines in out but not in ref", differ.getExtraLines1());
printList("# Lines in ref but not in out", differ.getExtraLines2());
printList("# Nodes in out but not in ref", differ.getNodes1());
printList("# Nodes in ref but not in out", differ.getNodes2());
printList("# Arcs in out but not in ref", differ.getArcs1());
printList("# Arcs in ref but not in out", differ.getArcs2());
}
System.out.println("\n\n");
}
if (!equal)
System.out.println("ERROR, some file are not structurally equal");
else
System.out.println("GOOD, all files are structurally equal");
}
private static void printList(String message, List extraOut) {
if (extraOut.size() > 0) {
System.out.println(message);
for (Object o : extraOut) {
System.out.println(o);
}
}
}
private static final class JavaFilter implements FilenameFilter {
public boolean accept(File dir, String name) {
return name.endsWith(".java");
}
}
}

View File

@ -0,0 +1,308 @@
/*
* UmlGraph class diagram testing framework
*
* Contibuted by Andrea Aime
* (C) Copyright 2005 Diomidis Spinellis
*
* Permission to use, copy, and distribute this software and its
* documentation for any purpose and without fee is hereby granted,
* provided that the above copyright notice appear in all copies and that
* both that copyright notice and this permission notice appear in
* supporting documentation.
*
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
* MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
*
* $Id$
*
*/
package gr.spinellis.umlgraph.test;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.io.StreamTokenizer;
import java.io.StringReader;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
public class DotDiff {
private List<DotNode> nodes1 = new ArrayList<DotNode>();
private List<DotNode> nodes2 = new ArrayList<DotNode>();
private List<DotArc> arcs1 = new ArrayList<DotArc>();
private List<DotArc> arcs2 = new ArrayList<DotArc>();
private List<String> extraLines1 = new ArrayList<String>();
private List<String> extraLines2 = new ArrayList<String>();
/**
* Builds a dot differ on the two files
*
* @param dotFirst
* @param dotSecond
* @throws IOException
*/
public DotDiff(File dotFirst, File dotSecond) throws IOException {
// gather the lines
List<String> lines1 = readGraphLines(dotFirst);
List<String> lines2 = readGraphLines(dotSecond);
// parse the lines
extraLines1 = parseLines(lines1, nodes1, arcs1);
extraLines2 = parseLines(lines2, nodes2, arcs2);
// diff extra lines
for (Iterator<String> it = extraLines1.iterator(); it.hasNext();) {
if (extraLines2.remove(it.next()))
it.remove();
}
// diff nodes
for (Iterator<DotNode> it = nodes1.iterator(); it.hasNext();) {
if (nodes2.remove(it.next()))
it.remove();
}
// diff arcs
for (Iterator<DotArc> it = arcs1.iterator(); it.hasNext();) {
if (arcs2.remove(it.next()))
it.remove();
}
}
/**
* Returns true if the dot files are structurally equal, that is, if every
* non comment and non header line of the first file appears in the second,
* and otherwise.
*
* @return
*/
public boolean graphEquals() {
return (extraLines1.size() + extraLines2.size() + nodes1.size() + nodes2.size()
+ arcs1.size() + arcs2.size()) == 0;
}
public List<DotArc> getArcs1() {
return arcs1;
}
public List<DotArc> getArcs2() {
return arcs2;
}
public List<String> getExtraLines1() {
return extraLines1;
}
public List<String> getExtraLines2() {
return extraLines2;
}
public List<DotNode> getNodes1() {
return nodes1;
}
public List<DotNode> getNodes2() {
return nodes2;
}
/**
* Reads all relevant lines from the dot file
*
* @param dotFile
* @return
* @throws IOException
*/
private List<String> readGraphLines(File dotFile) throws IOException {
List<String> lines = new ArrayList<String>();
BufferedReader br = null;
try {
br = new BufferedReader(new FileReader(dotFile));
String line;
while ((line = br.readLine()) != null) {
line = line.trim();
if (graphDefinitionLine(line))
lines.add(line);
}
} finally {
if (br != null)
br.close();
}
return lines;
}
/**
* Tells if a line is relevant or not (unrelevant lines are headers,
* comments, "digraf G {" and the closing "}" (to simplify matters we assume
* the file is properly structured).
*
* @param line
* @return
*/
private boolean graphDefinitionLine(String line) {
return !(line.startsWith("#") || line.startsWith("//") || line.equals("digraph G {") || line
.equals("}"));
}
private List<String> parseLines(List<String> lines, List<DotNode> nodeList, List<DotArc> arcs)
throws IOException {
List<String> extraLines = new ArrayList<String>();
List<String> arcLines = new ArrayList<String>();
Map<String, DotNode> nodes = new HashMap<String, DotNode>();
for (String line : lines) {
int openBrackedIdx = line.indexOf('[');
int closedBracketIdx = line.lastIndexOf(']');
int arrowIdx = line.indexOf("->");
if (openBrackedIdx < 0 && closedBracketIdx < 0 || line.startsWith("edge")
|| line.startsWith("node"))
extraLines.add(line);
else if (arrowIdx > 0 && arrowIdx < openBrackedIdx) { // that's an
arcLines.add(line);
} else { // that's a node
String attributes = line.substring(openBrackedIdx + 1, closedBracketIdx);
Map<String, String> attMap = parseAttributes(attributes);
String name = line.substring(0, openBrackedIdx - 1).trim();
String label = attMap.get("label");
DotNode node = new DotNode(name, label, attMap, line);
nodes.put(name, node);
nodeList.add(node);
}
}
for (String line : arcLines) {
int openBrackedIdx = line.indexOf('[');
int closedBracketIdx = line.lastIndexOf(']');
String attributes = line.substring(openBrackedIdx + 1, closedBracketIdx);
String[] names = line.substring(0, openBrackedIdx).split("->");
DotNode from = nodes.get(names[0].trim());
DotNode to = nodes.get(names[1].trim());
if (from == null) {
from = new DotNode(names[0], "", new HashMap<String, String>(), "");
}
if (to == null) {
to = new DotNode(names[1], "", new HashMap<String, String>(), "");
}
arcs.add(new DotArc(from, to, parseAttributes(attributes), line));
}
return extraLines;
}
private Map<String, String> parseAttributes(String attributes) throws IOException {
Map<String, String> map = new HashMap<String, String>();
StreamTokenizer st = new StreamTokenizer(new StringReader(attributes));
st.wordChars('_', '_');
st.wordChars('\\', '\\');
st.wordChars('\'', '\'');
int tokenType;
boolean isValue = false;
String attName = null;
String token = null;
while ((tokenType = st.nextToken()) != StreamTokenizer.TT_EOF) {
switch (tokenType) {
case StreamTokenizer.TT_NUMBER:
token = "" + st.nval;
break;
case StreamTokenizer.TT_WORD:
case '"':
case '\'':
token = st.sval;
break;
}
tokenType = st.nextToken();
if (isValue) {
map.put(attName, token);
isValue = false;
} else {
attName = token;
isValue = true;
}
}
return map;
}
private static class DotNode {
String name;
String label;
Map<String, String> attributes;
String line;
public DotNode(String name, String label, Map<String, String> attributes, String line) {
this.name = name;
this.label = label.replace("\n", "\\n");
this.attributes = attributes;
this.line = line.replace("\n", "\\n");
}
public boolean equals(Object other) {
if (!(other instanceof DotNode))
return false;
DotNode on = (DotNode) other;
if (label == null) // anonymous node
return on.label == null && on.name.equals(name) && on.attributes.equals(attributes);
else
return on.label.equals(label) && on.attributes.equals(attributes);
}
public int hashCode() {
return name.hashCode() + 17 * attributes.hashCode();
}
public String toString() {
return "Node: " + label + "; " + line;
}
}
private static class DotArc {
DotNode from;
DotNode to;
Map<String, String> attributes;
String line;
public DotArc(DotNode from, DotNode to, Map<String, String> attributes, String line) {
this.from = from;
this.to = to;
this.attributes = attributes;
this.line = line.replace("\n", "\\n");
}
public boolean equals(Object other) {
if (!(other instanceof DotArc))
return false;
DotArc oa = (DotArc) other;
return oa.from.equals(from) && oa.to.equals(to) && oa.attributes.equals(attributes);
}
public int hashCode() {
return from.hashCode() + 17 * (to.hashCode() + 17 * attributes.hashCode());
}
public String toString() {
return "Arc: " + from.label + " -> " + to.label + "; " + line;
}
}
}