Mercurial > hg4j
changeset 61:fac8e7fcc8b0
Simple test framework - capable of parsing Hg cmdline output to compare with Java result
author | Artem Tikhomirov <tikhomirov.artem@gmail.com> |
---|---|
date | Tue, 18 Jan 2011 18:32:49 +0100 |
parents | 613c936d74e4 |
children | 25819103de17 |
files | .classpath design.txt test/com/tmate/hgkit/ExecHelper.java test/com/tmate/hgkit/OutputParser.java test/com/tmate/hgkit/StatusOutputParser.java test/com/tmate/hgkit/TestStatus.java |
diffstat | 6 files changed, 275 insertions(+), 1 deletions(-) [+] |
line wrap: on
line diff
--- a/.classpath Tue Jan 18 00:30:41 2011 +0100 +++ b/.classpath Tue Jan 18 18:32:49 2011 +0100 @@ -1,6 +1,7 @@ <?xml version="1.0" encoding="UTF-8"?> <classpath> <classpathentry kind="src" path="src"/> + <classpathentry kind="src" path="test"/> <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/J2SE-1.5"/> <classpathentry kind="output" path="bin"/> </classpath>
--- a/design.txt Tue Jan 18 00:30:41 2011 +0100 +++ b/design.txt Tue Jan 18 18:32:49 2011 +0100 @@ -65,4 +65,6 @@ <<<<< Tests: -DataAccess - readBytes(length > memBufferSize, length*2 > memBufferSize) - to check impl is capable to read huge chunks of data, regardless of own buffer size \ No newline at end of file +DataAccess - readBytes(length > memBufferSize, length*2 > memBufferSize) - to check impl is capable to read huge chunks of data, regardless of own buffer size + +ExecHelper('cmd', OutputParser()).run(). StatusOutputParser, LogOutputParser extends OutputParser. construct java result similar to that of cmd, compare results \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/com/tmate/hgkit/ExecHelper.java Tue Jan 18 18:32:49 2011 +0100 @@ -0,0 +1,53 @@ +/* + * Copyright (c) 2011 Artem Tikhomirov + */ +package com.tmate.hgkit; + +import java.io.File; +import java.io.IOException; +import java.io.InputStreamReader; +import java.nio.CharBuffer; +import java.util.LinkedList; + +/** + * + * @author artem + */ +public class ExecHelper { + + private final OutputParser parser; + private final File dir; + + public ExecHelper(OutputParser outParser, File workingDir) { + parser = outParser; + dir = workingDir; + } + + public void run(String... cmd) throws IOException, InterruptedException { + Process p = new ProcessBuilder(cmd).directory(dir).redirectErrorStream(true).start(); +// Process p = Runtime.getRuntime().exec(cmd, null, dir); + InputStreamReader stdOut = new InputStreamReader(p.getInputStream()); + LinkedList<CharBuffer> l = new LinkedList<CharBuffer>(); + int r = -1; + CharBuffer b = null; + do { + if (b == null || b.remaining() < b.capacity() / 3) { + b = CharBuffer.allocate(512); + l.add(b); + } + r = stdOut.read(b); + } while (r != -1); + int total = 0; + for (CharBuffer cb : l) { + total += cb.position(); + cb.flip(); + } + CharBuffer res = CharBuffer.allocate(total); + for (CharBuffer cb : l) { + res.put(cb); + } + res.flip(); + p.waitFor(); + parser.parse(res); + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/com/tmate/hgkit/OutputParser.java Tue Jan 18 18:32:49 2011 +0100 @@ -0,0 +1,13 @@ +/* + * Copyright (c) 2011 Artem Tikhomirov + */ +package com.tmate.hgkit; + +/** + * + * @author artem + */ +public interface OutputParser { + + public void parse(CharSequence seq); +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/com/tmate/hgkit/StatusOutputParser.java Tue Jan 18 18:32:49 2011 +0100 @@ -0,0 +1,137 @@ +/* + * Copyright (c) 2011 Artem Tikhomirov + */ +package com.tmate.hgkit; + +import java.io.File; +import java.util.Collections; +import java.util.LinkedList; +import java.util.List; +import java.util.Map; +import java.util.TreeMap; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +/** + * + * @author artem + */ +public class StatusOutputParser implements OutputParser { + + private final Pattern pattern; + private List<String> modified, added, removed, clean, missing, unknown, ignored; + private Map<String, String> copied; + private final boolean winPathSeparator; + + public StatusOutputParser() { +// pattern = Pattern.compile("^([MAR?IC! ]) ([\\w \\.-/\\\\]+)$", Pattern.MULTILINE); + pattern = Pattern.compile("^([MAR?IC! ]) (.+)$", Pattern.MULTILINE); + winPathSeparator = File.separatorChar == '\\'; + } + + public void reset() { + modified = added = removed = clean = missing = unknown = ignored = null; + copied = null; + } + + public void parse(CharSequence seq) { + Matcher m = pattern.matcher(seq); + while (m.find()) { + String fname = m.group(2); + switch ((int) m.group(1).charAt(0)) { + case (int) 'M' : { + modified = doAdd(modified, fname); + break; + } + case (int) 'A' : { + added = doAdd(added, fname); + break; + } + case (int) 'R' : { + removed = doAdd(removed, fname); + break; + } + case (int) '?' : { + unknown = doAdd(unknown, fname); + break; + } + case (int) 'I' : { + ignored = doAdd(ignored, fname); + break; + } + case (int) 'C' : { + clean = doAdd(clean, fname); + break; + } + case (int) '!' : { + missing = doAdd(missing, fname); + break; + } + case (int) ' ' : { + if (copied == null) { + copied = new TreeMap<String, String>(); + } + // last added is copy destination + // to get or to remove it - depends on what StatusCollector does in this case + copied.put(fname, added.get(added.size() - 1)); + break; + } + } + } + } + + // + public List<String> getModified() { + return proper(modified); + } + + public List<String> getAdded() { + return proper(added); + } + + public List<String> getRemoved() { + return proper(removed); + } + + public Map<String,String> getCopied() { + if (copied == null) { + return Collections.emptyMap(); + } + return Collections.unmodifiableMap(copied); + } + + public List<String> getClean() { + return proper(clean); + } + + public List<String> getMissing() { + return proper(missing); + } + + public List<String> getUnknown() { + return proper(unknown); + } + + public List<String> getIgnored() { + return proper(ignored); + } + + private List<String> proper(List<String> l) { + if (l == null) { + return Collections.emptyList(); + } + return Collections.unmodifiableList(l); + } + + private List<String> doAdd(List<String> l, String s) { + if (l == null) { + l = new LinkedList<String>(); + } + if (winPathSeparator) { + // Java impl always give slashed path, while Hg uses local, os-specific convention + s = s.replace('\\', '/'); + } + l.add(s); + return l; + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/com/tmate/hgkit/TestStatus.java Tue Jan 18 18:32:49 2011 +0100 @@ -0,0 +1,68 @@ +/* + * Copyright (c) 2011 Artem Tikhomirov + */ +package com.tmate.hgkit; + +import java.io.File; +import java.util.Collection; +import java.util.LinkedList; +import java.util.List; + +import com.tmate.hgkit.fs.FileWalker; +import com.tmate.hgkit.fs.RepositoryLookup; +import com.tmate.hgkit.ll.HgRepository; +import com.tmate.hgkit.ll.StatusCollector; +import com.tmate.hgkit.ll.WorkingCopyStatusCollector; + +/** + * + * @author artem + */ +public class TestStatus { + + public static void main(String[] args) throws Exception { + final StatusOutputParser statusParser = new StatusOutputParser(); + ExecHelper eh = new ExecHelper(statusParser, null); + eh.run("hg", "status", "-A"); + // run java equivalent + HgRepository repo = new RepositoryLookup().detectFromWorkingDir(); + final WorkingCopyStatusCollector wcc = new WorkingCopyStatusCollector(repo, new FileWalker(new File(System.getProperty("user.dir")))); + StatusCollector.Record r = wcc.status(HgRepository.TIP); + // compare result + reportNotEqual("MODIFIED", r.getModified(), statusParser.getModified()); + reportNotEqual("ADDED", r.getAdded(), statusParser.getAdded()); + reportNotEqual("REMOVED", r.getRemoved(), statusParser.getRemoved()); + reportNotEqual("CLEAN", r.getClean(), statusParser.getClean()); + reportNotEqual("IGNORED", r.getIgnored(), statusParser.getIgnored()); + reportNotEqual("MISSING", r.getMissing(), statusParser.getMissing()); + reportNotEqual("UNKNOWN", r.getUnknown(), statusParser.getUnknown()); + // TODO compare equals + } + + private static <T> void reportNotEqual(String what, Collection<T> l1, Collection<T> l2) { + List<T> diff = difference(l1, l2); + System.out.print(what); + if (!diff.isEmpty()) { + System.out.print(" are NOT the same: "); + for (T t : diff) { + System.out.print(t); + System.out.print(", "); + } + System.out.println(); + } else { + System.out.println(" are the same"); + } + } + + private static <T> List<T> difference(Collection<T> l1, Collection<T> l2) { + LinkedList<T> result = new LinkedList<T>(l2); + for (T t : l1) { + if (l2.contains(t)) { + result.remove(t); + } else { + result.add(t); + } + } + return result; + } +}