commit 228d6564f8e7b6bec635216d64282423f407025a Author: Karsten Loesing karsten.loesing@gmx.net Date: Wed Dec 14 19:17:26 2011 +0100
Make consensus parsing a lot more robust. --- src/org/torproject/descriptor/DirSourceEntry.java | 3 + .../torproject/descriptor/NetworkStatusEntry.java | 25 +- .../descriptor/RelayNetworkStatusConsensus.java | 17 +- .../descriptor/impl/DescriptorParseException.java | 10 + .../descriptor/impl/DirSourceEntryImpl.java | 115 +++- .../descriptor/impl/NetworkStatusEntryImpl.java | 217 ++++-- .../torproject/descriptor/impl/ParseHelper.java | 147 +++ .../impl/RelayNetworkStatusConsensusImpl.java | 430 ++++++--- .../impl/RelayNetworkStatusVoteImpl.java | 15 +- .../impl/RelayNetworkStatusConsensusImplTest.java | 932 ++++++++++++-------- 10 files changed, 1307 insertions(+), 604 deletions(-)
diff --git a/src/org/torproject/descriptor/DirSourceEntry.java b/src/org/torproject/descriptor/DirSourceEntry.java index 57ce684..190b1df 100644 --- a/src/org/torproject/descriptor/DirSourceEntry.java +++ b/src/org/torproject/descriptor/DirSourceEntry.java @@ -22,6 +22,9 @@ public interface DirSourceEntry { /* Return the ORPort. */ public int getOrPort();
+ /* Return whether the dir-source was created using a legacy key. */ + public boolean isLegacy(); + /* Return the contact line. */ public String getContactLine();
diff --git a/src/org/torproject/descriptor/NetworkStatusEntry.java b/src/org/torproject/descriptor/NetworkStatusEntry.java index 156d07b..5d48818 100644 --- a/src/org/torproject/descriptor/NetworkStatusEntry.java +++ b/src/org/torproject/descriptor/NetworkStatusEntry.java @@ -30,16 +30,29 @@ public interface NetworkStatusEntry { /* Return the DirPort. */ public int getDirPort();
- /* Return the relay flags. */ + /* Return the relay flags or null if the status entry didn't contain any + * relay flags. */ public SortedSet<String> getFlags();
- /* Return the Tor software version. */ + /* Return the Tor software version or null if the status entry didn't + * contain a version line. */ public String getVersion();
- /* Return the bandwidth weight line. */ - public String getBandwidth(); + /* Return the bandwidth weight or -1L if the status entry didn't + * contain a bandwidth line. */ + public long getBandwidth();
- /* Return the port summary line. */ - public String getPorts(); + /* Return the measured bandwidth or -1L if the status entry didn't + * contain a bandwidth line or didn't contain a Measured= keyword in its + * bandwidth line. */ + public long getMeasured(); + + /* Return the default policy of the port summary or null if the status + * entry didn't contain a port summary line. */ + public String getDefaultPolicy(); + + /* Return the port list of the port summary or null if the status entry + * didn't contain a port summary line. */ + public String getPortList(); }
diff --git a/src/org/torproject/descriptor/RelayNetworkStatusConsensus.java b/src/org/torproject/descriptor/RelayNetworkStatusConsensus.java index 17beeb5..42757ce 100644 --- a/src/org/torproject/descriptor/RelayNetworkStatusConsensus.java +++ b/src/org/torproject/descriptor/RelayNetworkStatusConsensus.java @@ -24,8 +24,11 @@ public interface RelayNetworkStatusConsensus extends Descriptor { /* Return the valid-until time in milliseconds. */ public long getValidUntilMillis();
- /* Return a list of the voting-delay times in seconds. */ - public List<Long> getVotingDelay(); + /* Return the VoteSeconds time in seconds. */ + public long getVoteSeconds(); + + /* Return the DistSeconds time in seconds. */ + public long getDistSeconds();
/* Return recommended server versions or null if the consensus doesn't * contain recommended server versions. */ @@ -38,8 +41,9 @@ public interface RelayNetworkStatusConsensus extends Descriptor { /* Return known relay flags. */ public SortedSet<String> getKnownFlags();
- /* Return consensus parameters. */ - public SortedMap<String, String> getConsensusParams(); + /* Return consensus parameters or null if the consensus doesn't contain + * consensus parameters. */ + public SortedMap<String, Integer> getConsensusParams();
/* Return dir-source entries representing the directories of which * votes are contained in this consensus. */ @@ -58,7 +62,8 @@ public interface RelayNetworkStatusConsensus extends Descriptor { /* Return directory signatures. */ public SortedMap<String, String> getDirectorySignatures();
- /* Return bandwidth weights. */ - public SortedMap<String, String> getBandwidthWeights(); + /* Return bandwidth weights or null if the consensus doesn't contain + * bandwidth weights. */ + public SortedMap<String, Integer> getBandwidthWeights(); }
diff --git a/src/org/torproject/descriptor/impl/DescriptorParseException.java b/src/org/torproject/descriptor/impl/DescriptorParseException.java new file mode 100644 index 0000000..8670a3b --- /dev/null +++ b/src/org/torproject/descriptor/impl/DescriptorParseException.java @@ -0,0 +1,10 @@ +/* Copyright 2011 The Tor Project + * See LICENSE for licensing information */ +package org.torproject.descriptor.impl; + +public class DescriptorParseException extends Exception { + protected DescriptorParseException(String message) { + super(message); + } +} + diff --git a/src/org/torproject/descriptor/impl/DirSourceEntryImpl.java b/src/org/torproject/descriptor/impl/DirSourceEntryImpl.java index a2d0b34..a38da87 100644 --- a/src/org/torproject/descriptor/impl/DirSourceEntryImpl.java +++ b/src/org/torproject/descriptor/impl/DirSourceEntryImpl.java @@ -6,6 +6,8 @@ import java.io.BufferedReader; import java.io.IOException; import java.io.StringReader; import java.text.ParseException; +import java.util.SortedSet; +import java.util.TreeSet; import org.torproject.descriptor.DirSourceEntry;
public class DirSourceEntryImpl implements DirSourceEntry { @@ -16,30 +18,110 @@ public class DirSourceEntryImpl implements DirSourceEntry { }
protected DirSourceEntryImpl(byte[] dirSourceEntryBytes) - throws ParseException { + throws DescriptorParseException { this.dirSourceEntryBytes = dirSourceEntryBytes; + this.initializeKeywords(); + this.parseDirSourceEntryBytes(); + this.checkKeywords(); + } + + private SortedSet<String> exactlyOnceKeywords, atMostOnceKeywords; + private void initializeKeywords() { + this.exactlyOnceKeywords = new TreeSet<String>(); + this.exactlyOnceKeywords.add("dir-source"); + this.exactlyOnceKeywords.add("vote-digest"); + this.atMostOnceKeywords = new TreeSet<String>(); + this.atMostOnceKeywords.add("contact"); + } + + private void parsedExactlyOnceKeyword(String keyword) + throws DescriptorParseException { + if (!this.exactlyOnceKeywords.contains(keyword)) { + throw new DescriptorParseException("Duplicate '" + keyword + + "' line in dir-source."); + } + this.exactlyOnceKeywords.remove(keyword); + } + + private void parsedAtMostOnceKeyword(String keyword) + throws DescriptorParseException { + if (!this.atMostOnceKeywords.contains(keyword)) { + throw new DescriptorParseException("Duplicate " + keyword + "line " + + "in dir-source."); + } + this.atMostOnceKeywords.remove(keyword); + } + + private void checkKeywords() throws DescriptorParseException { + if (!this.exactlyOnceKeywords.isEmpty()) { + throw new DescriptorParseException("dir-source does not contain a '" + + this.exactlyOnceKeywords.first() + "' line."); + } + } + + private void parseDirSourceEntryBytes() + throws DescriptorParseException { try { BufferedReader br = new BufferedReader(new StringReader( new String(this.dirSourceEntryBytes))); String line; while ((line = br.readLine()) != null) { - if (line.startsWith("dir-source ")) { - String[] parts = line.split(" "); - this.nickname = parts[1]; - this.identity = parts[2]; - this.ip = parts[4]; - this.dirPort = Integer.parseInt(parts[5]); - this.orPort = Integer.parseInt(parts[6]); - } else if (line.startsWith("contact ")) { - this.contactLine = line.substring("contact ".length()); - } else if (line.startsWith("vote-digest ")) { - this.voteDigest = line.split(" ")[1]; + if (line.startsWith("dir-source")) { + this.parseDirSourceLine(line); + } else if (line.startsWith("contact")) { + this.parseContactLine(line); + } else if (line.startsWith("vote-digest")) { + this.parseVoteDigestLine(line); + } else { + /* TODO Should we really throw an exception here? */ + throw new DescriptorParseException("Unknown line '" + line + + "' in dir-source entry."); } } } catch (IOException e) { - /* TODO This cannot happen, right? */ + throw new RuntimeException("Internal error: Ran into an " + + "IOException while parsing a String in memory. Something's " + + "really wrong.", e); + } + } + + private void parseDirSourceLine(String line) + throws DescriptorParseException { + this.parsedExactlyOnceKeyword("dir-source"); + String[] parts = line.split(" "); + String nickname = parts[1]; + if (nickname.endsWith("-legacy")) { + nickname = nickname.substring(0, nickname.length() + - "-legacy".length()); + this.isLegacy = true; + this.parsedExactlyOnceKeyword("vote-digest"); + } + this.nickname = ParseHelper.parseNickname(line, nickname); + this.identity = ParseHelper.parseTwentyByteHexString(line, parts[2]); + this.ip = ParseHelper.parseIpv4Address(line, parts[4]); + this.dirPort = ParseHelper.parsePort(line, parts[5]); + this.orPort = ParseHelper.parsePort(line, parts[6]); + } + + private void parseContactLine(String line) + throws DescriptorParseException { + this.parsedAtMostOnceKeyword("contact"); + if (line.length() > "contact ".length()) { + this.contactLine = line.substring("contact ".length()); + } else { + this.contactLine = ""; + } + } + + private void parseVoteDigestLine(String line) + throws DescriptorParseException { + this.parsedExactlyOnceKeyword("vote-digest"); + String[] parts = line.split(" "); + if (parts.length != 2) { + throw new DescriptorParseException("Invalid line '" + line + "'."); } - /* TODO Implement some plausibility tests. */ + this.voteDigest = ParseHelper.parseTwentyByteHexString(line, + parts[1]); }
private String nickname; @@ -52,6 +134,11 @@ public class DirSourceEntryImpl implements DirSourceEntry { return this.identity; }
+ private boolean isLegacy; + public boolean isLegacy() { + return this.isLegacy; + } + private String ip; public String getIp() { return this.ip; diff --git a/src/org/torproject/descriptor/impl/NetworkStatusEntryImpl.java b/src/org/torproject/descriptor/impl/NetworkStatusEntryImpl.java index 610fb1a..6612272 100644 --- a/src/org/torproject/descriptor/impl/NetworkStatusEntryImpl.java +++ b/src/org/torproject/descriptor/impl/NetworkStatusEntryImpl.java @@ -5,14 +5,10 @@ package org.torproject.descriptor.impl; import java.io.BufferedReader; import java.io.IOException; import java.io.StringReader; -import java.text.ParseException; -import java.text.SimpleDateFormat; import java.util.Arrays; +import java.util.SortedMap; import java.util.SortedSet; -import java.util.TimeZone; import java.util.TreeSet; -import org.apache.commons.codec.binary.Base64; -import org.apache.commons.codec.binary.Hex; import org.torproject.descriptor.NetworkStatusEntry;
public class NetworkStatusEntryImpl implements NetworkStatusEntry { @@ -22,60 +18,163 @@ public class NetworkStatusEntryImpl implements NetworkStatusEntry { return this.statusEntryBytes; }
- private static SimpleDateFormat dateTimeFormat; - static { - dateTimeFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); - dateTimeFormat.setTimeZone(TimeZone.getTimeZone("UTC")); - } - protected NetworkStatusEntryImpl(byte[] statusEntryBytes) - throws ParseException { + throws DescriptorParseException { this.statusEntryBytes = statusEntryBytes; + this.initializeKeywords(); + this.parseStatusEntryBytes(); + } + + private SortedSet<String> atMostOnceKeywords; + private void initializeKeywords() { + this.atMostOnceKeywords = new TreeSet<String>(); + this.atMostOnceKeywords.add("s"); + this.atMostOnceKeywords.add("v"); + this.atMostOnceKeywords.add("w"); + this.atMostOnceKeywords.add("p"); + this.atMostOnceKeywords.add("m"); + } + + private void parsedAtMostOnceKeyword(String keyword) + throws DescriptorParseException { + if (!this.atMostOnceKeywords.contains(keyword)) { + throw new DescriptorParseException("Duplicate '" + keyword + + "' line in status entry."); + } + this.atMostOnceKeywords.remove(keyword); + } + + private void parseStatusEntryBytes() throws DescriptorParseException { try { BufferedReader br = new BufferedReader(new StringReader( new String(this.statusEntryBytes))); - String line; + String line = br.readLine(); + if (line == null || !line.startsWith("r ")) { + throw new DescriptorParseException("Status entry must start with " + + "an r line."); + } + String[] rLineParts = line.split(" "); + this.parseRLine(line, rLineParts); while ((line = br.readLine()) != null) { - if (line.startsWith("r ")) { - String[] parts = line.split(" "); - if (parts.length < 9) { - throw new RuntimeException("r line '" + line + "' has fewer " - + "space-separated elements than expected."); - } - this.nickname = parts[1]; - this.fingerprint = Hex.encodeHexString(Base64.decodeBase64( - parts[2] + "=")).toLowerCase(); - this.descriptor = Hex.encodeHexString(Base64.decodeBase64( - parts[3] + "=")).toLowerCase(); - this.publishedMillis = dateTimeFormat.parse(parts[4] + " " - + parts[5]).getTime(); - this.address = parts[6]; - this.orPort = Integer.parseInt(parts[7]); - this.dirPort = Integer.parseInt(parts[8]); - } else if (line.equals("s")) { - /* No flags to add. */ - } else if (line.startsWith("s ")) { - this.flags.addAll(Arrays.asList(line.substring("s ".length()). - split(" "))); - } else if (line.startsWith("v ") || line.startsWith("opt v")) { - this.version = line.substring( - line.startsWith("v ") ? "v ".length() : "opt v".length()); - } else if (line.startsWith("w ")) { - this.bandwidth = line.substring("w ".length()); - } else if (line.startsWith("p ")) { - this.ports = line.substring(2); - } else if (line.startsWith("m ")) { - /* TODO Parse m lines in votes. */ + String[] parts = !line.startsWith("opt ") ? line.split(" ") : + line.substring("opt ".length()).split(" "); + String keyword = parts[0]; + if (keyword.equals("s")) { + this.parseSLine(line, parts); + } else if (keyword.equals("v")) { + this.parseVLine(line, parts); + } else if (keyword.equals("w")) { + this.parseWLine(line, parts); + } else if (keyword.equals("p")) { + this.parsePLine(line, parts); + } else if (keyword.equals("m")) { + this.parseMLine(line, parts); } else { - throw new RuntimeException("Unknown line '" + line + "' in " - + "status entry."); + /* TODO Is throwing an exception the right thing to do here? + * This is probably fine for development, but once the library + * is in production use, this seems annoying. */ + throw new DescriptorParseException("Unknown line '" + line + + "' in status entry."); } } } catch (IOException e) { - /* TODO Do something. */ + throw new RuntimeException("Internal error: Ran into an " + + "IOException while parsing a String in memory. Something's " + + "really wrong.", e); + } + } + + private void parseRLine(String line, String[] parts) + throws DescriptorParseException { + if (parts.length < 9) { + throw new RuntimeException("r line '" + line + "' has fewer " + + "space-separated elements than expected."); + } + this.nickname = ParseHelper.parseNickname(line, parts[1]); + this.fingerprint = ParseHelper.parseTwentyByteBase64String(line, + parts[2]); + this.descriptor = ParseHelper.parseTwentyByteBase64String(line, + parts[3]); + this.publishedMillis = ParseHelper.parseTimestampAtIndex(line, parts, + 4, 5); + this.address = ParseHelper.parseIpv4Address(line, parts[6]); + this.orPort = ParseHelper.parsePort(line, parts[7]); + this.dirPort = ParseHelper.parsePort(line, parts[8]); + } + + private void parseSLine(String line, String[] parts) + throws DescriptorParseException { + this.parsedAtMostOnceKeyword("s"); + this.flags = new TreeSet<String>(); + for (int i = 1; i < parts.length; i++) { + this.flags.add(parts[i]); + } + } + + private void parseVLine(String line, String[] parts) + throws DescriptorParseException { + this.parsedAtMostOnceKeyword("v"); + String noOptLine = line; + if (noOptLine.startsWith("opt ")) { + noOptLine = noOptLine.substring(4); + } + if (noOptLine.length() < 3) { + throw new DescriptorParseException("Invalid line '" + line + "' in " + + "status entry."); + } else { + this.version = noOptLine.substring(2); + } + } + + private void parseWLine(String line, String[] parts) + throws DescriptorParseException { + this.parsedAtMostOnceKeyword("w"); + SortedMap<String, Integer> pairs = ParseHelper.parseKeyValuePairs( + line, parts, 1); + if (pairs.isEmpty()) { + throw new DescriptorParseException("Illegal line '" + line + "'."); + } + if (pairs.containsKey("Bandwidth")) { + this.bandwidth = pairs.remove("Bandwidth"); + } + if (pairs.containsKey("Measured")) { + this.measured = pairs.remove("Measured"); + } + if (!pairs.isEmpty()) { + throw new DescriptorParseException("Unknown key-value pair in " + + "line '" + line + "'."); } - /* TODO Add some plausibility checks, like if we have a nickname - * etc. */ + } + + private void parsePLine(String line, String[] parts) + throws DescriptorParseException { + this.parsedAtMostOnceKeyword("p"); + boolean isValid = true; + if (parts.length != 3) { + isValid = false; + } else if (!parts[1].equals("accept") && !parts[1].equals("reject")) { + isValid = false; + } else { + this.defaultPolicy = parts[1]; + this.portList = parts[2]; + String[] ports = parts[2].split(",", -1); + for (int i = 0; i < ports.length; i++) { + if (ports[i].length() < 1) { + isValid = false; + break; + } + } + } + if (!isValid) { + throw new DescriptorParseException("Illegal line '" + line + "'."); + } + } + + private void parseMLine(String line, String[] parts) + throws DescriptorParseException { + this.parsedAtMostOnceKeyword("m"); + /* TODO Implement parsing of m lines in votes. Try to find where m + * lines are specified first. */ }
private String nickname; @@ -113,7 +212,7 @@ public class NetworkStatusEntryImpl implements NetworkStatusEntry { return this.dirPort; }
- private SortedSet<String> flags = new TreeSet<String>(); + private SortedSet<String> flags; public SortedSet<String> getFlags() { return new TreeSet<String>(this.flags); } @@ -123,14 +222,24 @@ public class NetworkStatusEntryImpl implements NetworkStatusEntry { return this.version; }
- private String bandwidth; - public String getBandwidth() { + private long bandwidth = -1L; + public long getBandwidth() { return this.bandwidth; }
- private String ports; - public String getPorts() { - return this.ports; + private long measured = -1L; + public long getMeasured() { + return this.measured; + } + + private String defaultPolicy; + public String getDefaultPolicy() { + return this.defaultPolicy; + } + + private String portList; + public String getPortList() { + return this.portList; } }
diff --git a/src/org/torproject/descriptor/impl/ParseHelper.java b/src/org/torproject/descriptor/impl/ParseHelper.java new file mode 100644 index 0000000..5f4a1bd --- /dev/null +++ b/src/org/torproject/descriptor/impl/ParseHelper.java @@ -0,0 +1,147 @@ +/* Copyright 2011 The Tor Project + * See LICENSE for licensing information */ +package org.torproject.descriptor.impl; + +import java.text.ParseException; +import java.text.SimpleDateFormat; +import java.util.SortedMap; +import java.util.TimeZone; +import java.util.TreeMap; +import java.util.regex.Matcher; +import java.util.regex.Pattern; +import org.apache.commons.codec.binary.Base64; +import org.apache.commons.codec.binary.Hex; + +public class ParseHelper { + + private static Pattern ipv4Pattern = + Pattern.compile("^[0-9\.]{7,15}$"); + public static String parseIpv4Address(String line, String address) + throws DescriptorParseException { + boolean isValid = true; + if (!ipv4Pattern.matcher(address).matches()) { + isValid = false; + } else { + String[] parts = address.split("\.", -1); + if (parts.length != 4) { + isValid = false; + } else { + for (int i = 0; i < 4; i++) { + try { + int octetValue = Integer.parseInt(parts[i]); + if (octetValue < 0 || octetValue > 255) { + isValid = false; + } + } catch (NumberFormatException e) { + isValid = false; + } + } + } + } + if (!isValid) { + throw new DescriptorParseException("'" + address + "' in line '" + + line + "' is not a valid IPv4 address."); + } + return address; + } + + public static int parsePort(String line, String portString) + throws DescriptorParseException { + int port = -1; + try { + port = Integer.parseInt(portString); + } catch (NumberFormatException e) { + throw new DescriptorParseException("'" + portString + "' in line '" + + line + "' is not a valid port number."); + } + if (port < 0 || port > 65535) { + throw new DescriptorParseException("'" + portString + "' in line '" + + line + "' is not a valid port number."); + } + return port; + } + + private static SimpleDateFormat dateTimeFormat = new SimpleDateFormat( + "yyyy-MM-dd HH:mm:ss"); + static { + dateTimeFormat.setLenient(false); + dateTimeFormat.setTimeZone(TimeZone.getTimeZone("UTC")); + } + public static long parseTimestampAtIndex(String line, String[] parts, + int dateIndex, int timeIndex) throws DescriptorParseException { + if (dateIndex >= parts.length || timeIndex >= parts.length) { + throw new DescriptorParseException("Line '" + line + "' does not " + + "contain a timestamp at the expected position."); + } + long result = -1L; + try { + result = dateTimeFormat.parse( + parts[dateIndex] + " " + parts[timeIndex]).getTime(); + } catch (ParseException e) { + /* Leave result at -1L. */ + } + if (result < 0L || result > 2000000000000L) { + throw new DescriptorParseException("Illegal timestamp format in " + + "line '" + line + "'."); + } + return result; + } + + private static Pattern twentyByteHexPattern = + Pattern.compile("^[0-9A-F]{40}$"); + public static String parseTwentyByteHexString(String line, + String hexString) throws DescriptorParseException { + if (!twentyByteHexPattern.matcher(hexString).matches()) { + throw new DescriptorParseException("Illegal hex string in line '" + + line + "'."); + } + return hexString; + } + + public static SortedMap<String, Integer> parseKeyValuePairs(String line, + String[] parts, int startIndex) throws DescriptorParseException { + SortedMap<String, Integer> result = new TreeMap<String, Integer>(); + for (int i = startIndex; i < parts.length; i++) { + String pair = parts[i]; + String[] pairParts = pair.split("="); + if (pairParts.length != 2) { + throw new DescriptorParseException("Illegal key-value pair in " + + "line '" + line + "'."); + } + String pairName = pairParts[0]; + try { + int pairValue = Integer.parseInt(pairParts[1]); + result.put(pairName, pairValue); + } catch (NumberFormatException e) { + throw new DescriptorParseException("Illegal value in line '" + + line + "'."); + } + } + return result; + } + + private static Pattern nicknamePattern = + Pattern.compile("^[0-9a-zA-Z]{1,19}$"); + public static String parseNickname(String line, String nickname) + throws DescriptorParseException { + if (!nicknamePattern.matcher(nickname).matches()) { + throw new DescriptorParseException("Illegal nickname in line '" + + line + "'."); + } + return nickname; + } + + private static Pattern base64Pattern = + Pattern.compile("^[0-9a-zA-Z+/]{27}$"); + public static String parseTwentyByteBase64String(String line, + String base64String) throws DescriptorParseException { + if (!base64Pattern.matcher(base64String).matches()) { + throw new DescriptorParseException("'" + base64String + + "' in line '" + line + "' is not a valid base64-encoded " + + "20-byte value."); + } + return Hex.encodeHexString(Base64.decodeBase64(base64String + "=")). + toUpperCase(); + } +} + diff --git a/src/org/torproject/descriptor/impl/RelayNetworkStatusConsensusImpl.java b/src/org/torproject/descriptor/impl/RelayNetworkStatusConsensusImpl.java index 7cbe94c..0771382 100644 --- a/src/org/torproject/descriptor/impl/RelayNetworkStatusConsensusImpl.java +++ b/src/org/torproject/descriptor/impl/RelayNetworkStatusConsensusImpl.java @@ -13,8 +13,6 @@ import java.util.SortedSet; import java.util.TimeZone; import java.util.TreeMap; import java.util.TreeSet; -import java.text.ParseException; -import java.text.SimpleDateFormat; import org.torproject.descriptor.Descriptor; import org.torproject.descriptor.DirSourceEntry; import org.torproject.descriptor.NetworkStatusEntry; @@ -41,187 +39,324 @@ public class RelayNetworkStatusConsensusImpl } byte[] descBytes = new byte[end - start]; System.arraycopy(consensusBytes, start, descBytes, 0, end - start); - RelayNetworkStatusConsensus parsedConsensus = - new RelayNetworkStatusConsensusImpl(descBytes); - parsedConsensuses.add(parsedConsensus); start = end; + try { + RelayNetworkStatusConsensus parsedConsensus = + new RelayNetworkStatusConsensusImpl(descBytes); + parsedConsensuses.add(parsedConsensus); + } catch (DescriptorParseException e) { + /* TODO Handle this error somehow. */ + System.err.println("Failed to parse consensus. Skipping."); + e.printStackTrace(); + } } return parsedConsensuses; }
- protected RelayNetworkStatusConsensusImpl(byte[] consensusBytes) { + protected RelayNetworkStatusConsensusImpl(byte[] consensusBytes) + throws DescriptorParseException { this.consensusBytes = consensusBytes; + this.initializeKeywords(); this.parseConsensusBytes(); - this.checkConsistency(); - /* TODO Find a way to handle parse and consistency-check problems. */ + this.checkKeywords(); + } + + private SortedSet<String> exactlyOnceKeywords, atMostOnceKeywords; + private void initializeKeywords() { + this.exactlyOnceKeywords = new TreeSet<String>(); + this.exactlyOnceKeywords.add("vote-status"); + this.exactlyOnceKeywords.add("consensus-method"); + this.exactlyOnceKeywords.add("valid-after"); + this.exactlyOnceKeywords.add("fresh-until"); + this.exactlyOnceKeywords.add("valid-until"); + this.exactlyOnceKeywords.add("voting-delay"); + this.exactlyOnceKeywords.add("known-flags"); + this.exactlyOnceKeywords.add("directory-footer"); + this.atMostOnceKeywords = new TreeSet<String>(); + this.atMostOnceKeywords.add("client-versions"); + this.atMostOnceKeywords.add("server-versions"); + this.atMostOnceKeywords.add("params"); + this.atMostOnceKeywords.add("bandwidth-weights"); + } + + private void parsedExactlyOnceKeyword(String keyword) + throws DescriptorParseException { + if (!this.exactlyOnceKeywords.contains(keyword)) { + throw new DescriptorParseException("Duplicate '" + keyword + + "' line in consensus."); + } + this.exactlyOnceKeywords.remove(keyword); + } + + private void parsedAtMostOnceKeyword(String keyword) + throws DescriptorParseException { + if (!this.atMostOnceKeywords.contains(keyword)) { + throw new DescriptorParseException("Duplicate " + keyword + "line " + + "in consensus."); + } + this.atMostOnceKeywords.remove(keyword); + } + + private void checkKeywords() throws DescriptorParseException { + if (!this.exactlyOnceKeywords.isEmpty()) { + throw new DescriptorParseException("Consensus does not contain a '" + + this.exactlyOnceKeywords.first() + "' line."); + } }
- private void parseConsensusBytes() { + private void parseConsensusBytes() throws DescriptorParseException { try { BufferedReader br = new BufferedReader(new StringReader( new String(this.consensusBytes))); - String line; - SimpleDateFormat dateTimeFormat = new SimpleDateFormat( - "yyyy-MM-dd HH:mm:ss"); - dateTimeFormat.setTimeZone(TimeZone.getTimeZone("UTC")); + String line = br.readLine(); + if (line == null || !line.equals("network-status-version 3")) { + throw new DescriptorParseException("Consensus must start with " + + "line 'network-status-version 3'."); + } + this.networkStatusVersion = 3; StringBuilder dirSourceEntryLines = null, statusEntryLines = null; boolean skipSignature = false; while ((line = br.readLine()) != null) { - if (line.startsWith("network-status-version ")) { - this.networkStatusVersion = Integer.parseInt(line.substring( - "network-status-version ".length())); - } else if (line.startsWith("vote-status ")) { - if (!line.equals("vote-status consensus")) { - throw new RuntimeException("Line '" + line + "' indicates " - + "that this string is not a consensus. Aborting " - + "parsing."); - } - } else if (line.startsWith("consensus-method ")) { - this.consensusMethod = Integer.parseInt(line.substring( - "consensus-method ".length())); - } else if (line.startsWith("valid-after ")) { - this.validAfterMillis = dateTimeFormat.parse( - line.substring("valid-after ".length())).getTime(); - } else if (line.startsWith("fresh-until ")) { - this.freshUntilMillis = dateTimeFormat.parse( - line.substring("fresh-until ".length())).getTime(); - } else if (line.startsWith("valid-until ")) { - this.validUntilMillis = dateTimeFormat.parse( - line.substring("valid-until ".length())).getTime(); - } else if (line.startsWith("voting-delay ")) { - for (String votingDelayString : line.substring( - "voting-delay ".length()).split(" ")) { - this.votingDelay.add(Long.parseLong(votingDelayString)); - } - } else if (line.startsWith("client-versions ")) { - this.recommendedClientVersions = new TreeSet<String>( - Arrays.asList(line.split(" ")[1].split(","))); - } else if (line.startsWith("server-versions ")) { - this.recommendedServerVersions = new TreeSet<String>( - Arrays.asList(line.split(" ")[1].split(","))); - } else if (line.startsWith("known-flags ")) { - for (String flag : line.substring("known-flags ".length()). - split(" ")) { - this.knownFlags.add(flag); - } - } else if (line.startsWith("params ")) { - if (line.length() > "params ".length()) { - for (String param : - line.substring("params ".length()).split(" ")) { - String paramName = param.split("=")[0]; - String paramValue = param.split("=")[1]; - this.consensusParams.put(paramName, paramValue); - } - } - } else if (line.startsWith("dir-source ") || - line.startsWith("r ") || line.equals("directory-footer")) { - /* TODO Add code for parsing legacy dir sources. */ + if (line.length() < 1) { + throw new DescriptorParseException("Empty lines are not " + + "allowed in a consensus."); + } + String[] parts = line.split(" "); + if (parts.length < 1) { + throw new DescriptorParseException("No keyword found in line '" + + line + "'."); + } + String keyword = parts[0]; + if (keyword.length() < 1) { + throw new DescriptorParseException("Empty keyword in line '" + + line + "'."); + } + if (keyword.equals("vote-status")) { + this.parseVoteStatusLine(line, parts); + } else if (keyword.equals("consensus-method")) { + this.parseConsensusMethodLine(line, parts); + } else if (keyword.equals("valid-after")) { + this.parseValidAfterLine(line, parts); + } else if (keyword.equals("fresh-until")) { + this.parseFreshUntilLine(line, parts); + } else if (keyword.equals("valid-until")) { + this.parseValidUntilLine(line, parts); + } else if (keyword.equals("voting-delay")) { + this.parseVotingDelayLine(line, parts); + } else if (keyword.equals("client-versions")) { + this.parseClientVersionsLine(line, parts); + } else if (keyword.equals("server-versions")) { + this.parseServerVersionsLine(line, parts); + } else if (keyword.equals("known-flags")) { + this.parseKnownFlagsLine(line, parts); + } else if (keyword.equals("params")) { + this.parseParamsLine(line, parts); + } else if (keyword.equals("dir-source") || keyword.equals("r") || + keyword.equals("directory-footer")) { if (dirSourceEntryLines != null) { - DirSourceEntry dirSourceEntry = new DirSourceEntryImpl( - dirSourceEntryLines.toString().getBytes()); - this.dirSourceEntries.put(dirSourceEntry.getIdentity(), - dirSourceEntry); + this.parseDirSourceEntryLines(dirSourceEntryLines.toString()); dirSourceEntryLines = null; } if (statusEntryLines != null) { - NetworkStatusEntryImpl statusEntry = - new NetworkStatusEntryImpl( - statusEntryLines.toString().getBytes()); - this.statusEntries.put(statusEntry.getFingerprint(), - statusEntry); + this.parseStatusEntryLines(statusEntryLines.toString()); statusEntryLines = null; } - if (line.startsWith("dir-source ")) { - dirSourceEntryLines = new StringBuilder(); - dirSourceEntryLines.append(line + "\n"); - } else if (line.startsWith("r ")) { - statusEntryLines = new StringBuilder(); - statusEntryLines.append(line + "\n"); + if (keyword.equals("dir-source")) { + dirSourceEntryLines = new StringBuilder(line + "\n"); + } else if (keyword.equals("r")) { + statusEntryLines = new StringBuilder(line + "\n"); + } else if (keyword.equals("directory-footer")) { + this.parsedExactlyOnceKeyword("directory-footer"); + } + } else if (keyword.equals("contact") || + keyword.equals("vote-digest")) { + if (dirSourceEntryLines == null) { + throw new DescriptorParseException(keyword + " line with no " + + "preceding dir-source line."); } - } else if (line.startsWith("contact ") || - line.startsWith("vote-digest ")) { dirSourceEntryLines.append(line + "\n"); - } else if (line.startsWith("s ") || line.equals("s") || - line.startsWith("v ") || line.startsWith("w ") || - line.startsWith("p ")) { - statusEntryLines.append(line + "\n"); - } else if (line.startsWith("bandwidth-weights ")) { - if (line.length() > "bandwidth-weights ".length()) { - for (String weight : line.substring("bandwidth-weights ". - length()).split(" ")) { - String weightName = weight.split("=")[0]; - String weightValue = weight.split("=")[1]; - this.bandwidthWeights.put(weightName, weightValue); - } + } else if (keyword.equals("s") || keyword.equals("v") || + keyword.equals("w") || keyword.equals("p")) { + if (statusEntryLines == null) { + throw new DescriptorParseException(keyword + " line with no " + + "preceding r line."); } - - } else if (line.startsWith("directory-signature ")) { - String[] parts = line.split(" "); - String identity = parts[1]; - String signingKeyDigest = parts[2]; - this.directorySignatures.put(identity, signingKeyDigest); + statusEntryLines.append(line + "\n"); + } else if (keyword.equals("bandwidth-weights")) { + this.parseBandwidthWeightsLine(line, parts); + } else if (keyword.equals("directory-signature")) { + this.parseDirectorySignatureLine(line, parts); } else if (line.equals("-----BEGIN SIGNATURE-----")) { skipSignature = true; } else if (line.equals("-----END SIGNATURE-----")) { skipSignature = false; } else if (!skipSignature) { - throw new RuntimeException("Unrecognized line '" + line + "'."); + /* TODO Is throwing an exception the right thing to do here? + * This is probably fine for development, but once the library + * is in production use, this seems annoying. */ + throw new DescriptorParseException("Unrecognized line '" + line + + "'."); } } } catch (IOException e) { throw new RuntimeException("Internal error: Ran into an " + "IOException while parsing a String in memory. Something's " + "really wrong.", e); - } catch (ParseException e) { - /* TODO Handle me. */ - } catch (NumberFormatException e) { - /* TODO Handle me. In theory, we shouldn't catch runtime - * exceptions, but in this case it keeps the parsing code small. */ - } catch (ArrayIndexOutOfBoundsException e) { - /* TODO Handle me. In theory, we shouldn't catch runtime - * exceptions, but in this case it keeps the parsing code small. */ } }
- private void checkConsistency() { - if (this.networkStatusVersion == 0) { - throw new RuntimeException("Consensus doesn't contain a " - + "'network-status-version' line."); + private void parseVoteStatusLine(String line, String[] parts) + throws DescriptorParseException { + this.parsedExactlyOnceKeyword("vote-status"); + if (parts.length != 2 || !parts[1].equals("consensus")) { + throw new DescriptorParseException("Line '" + line + "' indicates " + + "that this is not a consensus."); } - if (this.consensusMethod == 0) { - throw new RuntimeException("Consensus doesn't contain a " - + "'consensus-method' line."); + } + + private void parseConsensusMethodLine(String line, String[] parts) + throws DescriptorParseException { + this.parsedExactlyOnceKeyword("consensus-method"); + if (parts.length != 2) { + throw new DescriptorParseException("Illegal line '" + line + + "' in consensus."); } - if (this.validAfterMillis == 0L) { - throw new RuntimeException("Consensus doesn't contain a " - + "'valid-after' line."); + try { + this.consensusMethod = Integer.parseInt(parts[1]); + } catch (NumberFormatException e) { + throw new DescriptorParseException("Illegal consensus method " + + "number in line '" + line + "'."); } - if (this.freshUntilMillis == 0L) { - throw new RuntimeException("Consensus doesn't contain a " - + "'fresh-until' line."); + if (this.consensusMethod < 1) { + throw new DescriptorParseException("Illegal consensus method " + + "number in line '" + line + "'."); } - if (this.validUntilMillis == 0L) { - throw new RuntimeException("Consensus doesn't contain a " - + "'valid-until' line."); + } + + private void parseValidAfterLine(String line, String[] parts) + throws DescriptorParseException { + this.parsedExactlyOnceKeyword("valid-after"); + this.validAfterMillis = ParseHelper.parseTimestampAtIndex(line, parts, + 1, 2); + } + + private void parseFreshUntilLine(String line, String[] parts) + throws DescriptorParseException { + this.parsedExactlyOnceKeyword("fresh-until"); + this.freshUntilMillis = ParseHelper.parseTimestampAtIndex(line, parts, + 1, 2); + } + + private void parseValidUntilLine(String line, String[] parts) + throws DescriptorParseException { + this.parsedExactlyOnceKeyword("valid-until"); + this.validUntilMillis = ParseHelper.parseTimestampAtIndex(line, parts, + 1, 2); + } + + private void parseVotingDelayLine(String line, String[] parts) + throws DescriptorParseException { + this.parsedExactlyOnceKeyword("voting-delay"); + if (parts.length != 3) { + throw new DescriptorParseException("Wrong number of values in line " + + "'" + line + "'."); } - if (this.votingDelay.isEmpty()) { - throw new RuntimeException("Consensus doesn't contain a " - + "'voting-delay' line."); + try { + this.voteSeconds = Long.parseLong(parts[1]); + this.distSeconds = Long.parseLong(parts[2]); + } catch (NumberFormatException e) { + throw new DescriptorParseException("Illegal values in line '" + line + + "'."); + } + } + + private void parseClientVersionsLine(String line, String[] parts) + throws DescriptorParseException { + this.parsedAtMostOnceKeyword("client-versions"); + this.recommendedClientVersions = this.parseClientOrServerVersions( + line, parts); + } + + private void parseServerVersionsLine(String line, String[] parts) + throws DescriptorParseException { + this.parsedAtMostOnceKeyword("server-versions"); + this.recommendedServerVersions = this.parseClientOrServerVersions( + line, parts); + } + + private SortedSet<String> parseClientOrServerVersions(String line, + String[] parts) throws DescriptorParseException { + SortedSet<String> result = new TreeSet<String>(); + if (parts.length == 1) { + return result; + } else if (parts.length > 2) { + throw new DescriptorParseException("Illegal versions line '" + line + + "'."); } - if (this.knownFlags.isEmpty()) { - throw new RuntimeException("Consensus doesn't contain a " - + "'known-flags' line."); + String[] versions = parts[1].split(",", -1); + for (int i = 0; i < versions.length; i++) { + String version = versions[i]; + if (version.length() < 1) { + throw new DescriptorParseException("Illegal versions line '" + + line + "'."); + } + result.add(version); } - if (this.dirSourceEntries.isEmpty()) { - throw new RuntimeException("Consensus doesn't contain any " - + "'dir-source' lines."); + return result; + } + + private void parseKnownFlagsLine(String line, String[] parts) + throws DescriptorParseException { + this.parsedExactlyOnceKeyword("known-flags"); + if (parts.length < 2) { + throw new DescriptorParseException("No known flags in line '" + line + + "'."); } - if (this.statusEntries.isEmpty()) { - throw new RuntimeException("Consensus doesn't contain any 'r' " - + "lines."); + for (int i = 1; i < parts.length; i++) { + this.knownFlags.add(parts[i]); } }
+ private void parseParamsLine(String line, String[] parts) + throws DescriptorParseException { + this.parsedAtMostOnceKeyword("params"); + this.consensusParams = ParseHelper.parseKeyValuePairs(line, parts, 1); + } + + private void parseDirSourceEntryLines(String string) + throws DescriptorParseException { + DirSourceEntry dirSourceEntry = new DirSourceEntryImpl( + string.getBytes()); + this.dirSourceEntries.put(dirSourceEntry.getIdentity(), + dirSourceEntry); + } + + private void parseStatusEntryLines(String string) + throws DescriptorParseException { + NetworkStatusEntryImpl statusEntry = new NetworkStatusEntryImpl( + string.getBytes()); + this.statusEntries.put(statusEntry.getFingerprint(), statusEntry); + } + + private void parseBandwidthWeightsLine(String line, String[] parts) + throws DescriptorParseException { + this.parsedAtMostOnceKeyword("bandwidth-weights"); + this.bandwidthWeights = ParseHelper.parseKeyValuePairs(line, parts, + 1); + } + + private void parseDirectorySignatureLine(String line, String[] parts) + throws DescriptorParseException { + if (parts.length != 3) { + throw new DescriptorParseException("Illegal line '" + line + "'."); + } + String identity = ParseHelper.parseTwentyByteHexString(line, + parts[1]); + String signingKeyDigest = ParseHelper.parseTwentyByteHexString(line, + parts[2]); + this.directorySignatures.put(identity, signingKeyDigest); + } + private byte[] consensusBytes; public byte[] getRawDescriptorBytes() { return this.consensusBytes; @@ -252,9 +387,14 @@ public class RelayNetworkStatusConsensusImpl return this.validUntilMillis; }
- private List<Long> votingDelay = new ArrayList<Long>(); - public List<Long> getVotingDelay() { - return new ArrayList<Long>(this.votingDelay); + private long voteSeconds; + public long getVoteSeconds() { + return this.voteSeconds; + } + + private long distSeconds; + public long getDistSeconds() { + return this.distSeconds; }
private SortedSet<String> recommendedClientVersions; @@ -274,10 +414,10 @@ public class RelayNetworkStatusConsensusImpl return new TreeSet<String>(this.knownFlags); }
- private SortedMap<String, String> consensusParams = - new TreeMap<String, String>(); - public SortedMap<String, String> getConsensusParams() { - return new TreeMap<String, String>(this.consensusParams); + private SortedMap<String, Integer> consensusParams; + public SortedMap<String, Integer> getConsensusParams() { + return this.consensusParams == null ? null: + new TreeMap<String, Integer>(this.consensusParams); }
private SortedMap<String, DirSourceEntry> dirSourceEntries = @@ -304,10 +444,10 @@ public class RelayNetworkStatusConsensusImpl return new TreeMap<String, String>(this.directorySignatures); }
- private SortedMap<String, String> bandwidthWeights = - new TreeMap<String, String>(); - public SortedMap<String, String> getBandwidthWeights() { - return new TreeMap<String, String>(this.bandwidthWeights); + private SortedMap<String, Integer> bandwidthWeights; + public SortedMap<String, Integer> getBandwidthWeights() { + return this.bandwidthWeights == null ? null : + new TreeMap<String, Integer>(this.bandwidthWeights); } }
diff --git a/src/org/torproject/descriptor/impl/RelayNetworkStatusVoteImpl.java b/src/org/torproject/descriptor/impl/RelayNetworkStatusVoteImpl.java index bf2668b..238a512 100644 --- a/src/org/torproject/descriptor/impl/RelayNetworkStatusVoteImpl.java +++ b/src/org/torproject/descriptor/impl/RelayNetworkStatusVoteImpl.java @@ -149,11 +149,16 @@ public class RelayNetworkStatusVoteImpl } else if (line.startsWith("r ") || line.equals("directory-footer")) { if (statusEntryLines != null) { - NetworkStatusEntryImpl statusEntry = - new NetworkStatusEntryImpl( - statusEntryLines.toString().getBytes()); - this.statusEntries.put(statusEntry.getFingerprint(), - statusEntry); + try { + NetworkStatusEntryImpl statusEntry = + new NetworkStatusEntryImpl( + statusEntryLines.toString().getBytes()); + this.statusEntries.put(statusEntry.getFingerprint(), + statusEntry); + } catch (DescriptorParseException e) { + System.err.println("Could not parse status entry in vote. " + + "Skipping."); + } statusEntryLines = null; } if (line.startsWith("r ")) { diff --git a/test/org/torproject/descriptor/impl/RelayNetworkStatusConsensusImplTest.java b/test/org/torproject/descriptor/impl/RelayNetworkStatusConsensusImplTest.java index 4a7a7be..520473d 100644 --- a/test/org/torproject/descriptor/impl/RelayNetworkStatusConsensusImplTest.java +++ b/test/org/torproject/descriptor/impl/RelayNetworkStatusConsensusImplTest.java @@ -21,94 +21,120 @@ public class RelayNetworkStatusConsensusImplTest { * modifications requested by test methods. */ private static class ConsensusBuilder { private String networkStatusVersionLine = "network-status-version 3"; - private static void createWithNetworkStatusVersionLine(String line) { + private static RelayNetworkStatusConsensus + createWithNetworkStatusVersionLine(String line) + throws DescriptorParseException { ConsensusBuilder cb = new ConsensusBuilder(); cb.networkStatusVersionLine = line; - new RelayNetworkStatusConsensusImpl(cb.buildConsensus()); + return new RelayNetworkStatusConsensusImpl(cb.buildConsensus()); } private String voteStatusLine = "vote-status consensus"; - private static void createWithVoteStatusLine(String line) { + private static RelayNetworkStatusConsensus + createWithVoteStatusLine(String line) + throws DescriptorParseException { ConsensusBuilder cb = new ConsensusBuilder(); cb.voteStatusLine = line; - new RelayNetworkStatusConsensusImpl(cb.buildConsensus()); + return new RelayNetworkStatusConsensusImpl(cb.buildConsensus()); } private String consensusMethodLine = "consensus-method 11"; - private static void createWithConsensusMethodLine(String line) { + private static RelayNetworkStatusConsensus + createWithConsensusMethodLine(String line) + throws DescriptorParseException { ConsensusBuilder cb = new ConsensusBuilder(); cb.consensusMethodLine = line; - new RelayNetworkStatusConsensusImpl(cb.buildConsensus()); + return new RelayNetworkStatusConsensusImpl(cb.buildConsensus()); } private String validAfterLine = "valid-after 2011-11-30 09:00:00"; - private static void createWithValidAfterLine(String line) { + private static RelayNetworkStatusConsensus + createWithValidAfterLine(String line) + throws DescriptorParseException { ConsensusBuilder cb = new ConsensusBuilder(); cb.validAfterLine = line; - new RelayNetworkStatusConsensusImpl(cb.buildConsensus()); + return new RelayNetworkStatusConsensusImpl(cb.buildConsensus()); } private String freshUntilLine = "fresh-until 2011-11-30 10:00:00"; - private static void createWithFreshUntilLine(String line) { + private static RelayNetworkStatusConsensus + createWithFreshUntilLine(String line) + throws DescriptorParseException { ConsensusBuilder cb = new ConsensusBuilder(); cb.freshUntilLine = line; - new RelayNetworkStatusConsensusImpl(cb.buildConsensus()); + return new RelayNetworkStatusConsensusImpl(cb.buildConsensus()); } private String validUntilLine = "valid-until 2011-11-30 12:00:00"; - private static void createWithValidUntilLine(String line) { + private static RelayNetworkStatusConsensus + createWithValidUntilLine(String line) + throws DescriptorParseException { ConsensusBuilder cb = new ConsensusBuilder(); cb.validUntilLine = line; - new RelayNetworkStatusConsensusImpl(cb.buildConsensus()); + return new RelayNetworkStatusConsensusImpl(cb.buildConsensus()); } private String votingDelayLine = "voting-delay 300 300"; - private static void createWithVotingDelayLine(String line) { + private static RelayNetworkStatusConsensus + createWithVotingDelayLine(String line) + throws DescriptorParseException { ConsensusBuilder cb = new ConsensusBuilder(); cb.votingDelayLine = line; - new RelayNetworkStatusConsensusImpl(cb.buildConsensus()); + return new RelayNetworkStatusConsensusImpl(cb.buildConsensus()); } private String clientVersionsLine = "client-versions 0.2.1.31," + "0.2.2.34,0.2.3.6-alpha,0.2.3.7-alpha,0.2.3.8-alpha"; - private static void createWithClientVersionsLine(String line) { + private static RelayNetworkStatusConsensus + createWithClientVersionsLine(String line) + throws DescriptorParseException { ConsensusBuilder cb = new ConsensusBuilder(); cb.clientVersionsLine = line; - new RelayNetworkStatusConsensusImpl(cb.buildConsensus()); + return new RelayNetworkStatusConsensusImpl(cb.buildConsensus()); } private String serverVersionsLine = "server-versions 0.2.1.31," + "0.2.2.34,0.2.3.6-alpha,0.2.3.7-alpha,0.2.3.8-alpha"; - private static void createWithServerVersionsLine(String line) { + private static RelayNetworkStatusConsensus + createWithServerVersionsLine(String line) + throws DescriptorParseException { ConsensusBuilder cb = new ConsensusBuilder(); cb.serverVersionsLine = line; - new RelayNetworkStatusConsensusImpl(cb.buildConsensus()); + return new RelayNetworkStatusConsensusImpl(cb.buildConsensus()); } private String knownFlagsLine = "known-flags Authority BadExit Exit " + "Fast Guard HSDir Named Running Stable Unnamed V2Dir Valid"; - private static void createWithKnownFlagsLine(String line) { + private static RelayNetworkStatusConsensus + createWithKnownFlagsLine(String line) + throws DescriptorParseException { ConsensusBuilder cb = new ConsensusBuilder(); cb.knownFlagsLine = line; - new RelayNetworkStatusConsensusImpl(cb.buildConsensus()); + return new RelayNetworkStatusConsensusImpl(cb.buildConsensus()); } private String paramsLine = "params " + "CircuitPriorityHalflifeMsec=30000 bwauthbestratio=1 " + "bwauthcircs=1 bwauthdescbw=0 bwauthkp=10000 bwauthpid=1 " + "bwauthtd=5000 bwauthti=50000 bwauthtidecay=5000 cbtnummodes=3 " + "cbtquantile=80 circwindow=1000 refuseunknownexits=1"; - private static void createWithParamsLine(String line) { + private static RelayNetworkStatusConsensus + createWithParamsLine(String line) + throws DescriptorParseException { ConsensusBuilder cb = new ConsensusBuilder(); cb.paramsLine = line; - new RelayNetworkStatusConsensusImpl(cb.buildConsensus()); + return new RelayNetworkStatusConsensusImpl(cb.buildConsensus()); } private List<String> dirSources = new ArrayList<String>(); private List<String> statusEntries = new ArrayList<String>(); private String directoryFooterLine = "directory-footer"; - private static void createWithDirectoryFooterLine(String line) { + private static RelayNetworkStatusConsensus + createWithDirectoryFooterLine(String line) + throws DescriptorParseException { ConsensusBuilder cb = new ConsensusBuilder(); cb.directoryFooterLine = line; - new RelayNetworkStatusConsensusImpl(cb.buildConsensus()); + return new RelayNetworkStatusConsensusImpl(cb.buildConsensus()); } private String bandwidthWeightsLine = "bandwidth-weights Wbd=285 " + "Wbe=0 Wbg=0 Wbm=10000 Wdb=10000 Web=10000 Wed=1021 Wee=10000 " + "Weg=1021 Wem=10000 Wgb=10000 Wgd=8694 Wgg=10000 Wgm=10000 " + "Wmb=10000 Wmd=285 Wme=0 Wmg=0 Wmm=10000"; - private static void createWithBandwidthWeightsLine(String line) { + private static RelayNetworkStatusConsensus + createWithBandwidthWeightsLine(String line) + throws DescriptorParseException { ConsensusBuilder cb = new ConsensusBuilder(); cb.bandwidthWeightsLine = line; - new RelayNetworkStatusConsensusImpl(cb.buildConsensus()); + return new RelayNetworkStatusConsensusImpl(cb.buildConsensus()); } private List<String> directorySignatures = new ArrayList<String>(); private ConsensusBuilder() { @@ -217,60 +243,78 @@ public class RelayNetworkStatusConsensusImplTest { /* Helper class to build a directory source based on default data and * modifications requested by test methods. */ private static class DirSourceBuilder { - private static void createWithDirSource(String dirSourceString) { + private static RelayNetworkStatusConsensus + createWithDirSource(String dirSourceString) + throws DescriptorParseException { ConsensusBuilder cb = new ConsensusBuilder(); cb.dirSources.add(dirSourceString); - new RelayNetworkStatusConsensusImpl(cb.buildConsensus()); + return new RelayNetworkStatusConsensusImpl(cb.buildConsensus()); } private String nickname = "gabelmoo"; - private static void createWithNickname(String string) { + private static RelayNetworkStatusConsensus + createWithNickname(String string) + throws DescriptorParseException { DirSourceBuilder dsb = new DirSourceBuilder(); dsb.nickname = string; - createWithDirSource(dsb.buildDirSource()); + return createWithDirSource(dsb.buildDirSource()); } private String identity = "ED03BB616EB2F60BEC80151114BB25CEF515B226"; - private static void createWithIdentity(String string) { + private static RelayNetworkStatusConsensus + createWithIdentity(String string) + throws DescriptorParseException { DirSourceBuilder dsb = new DirSourceBuilder(); dsb.identity = string; - createWithDirSource(dsb.buildDirSource()); + return createWithDirSource(dsb.buildDirSource()); } private String hostName = "212.112.245.170"; - private static void createWithHostName(String string) { + private static RelayNetworkStatusConsensus + createWithHostName(String string) + throws DescriptorParseException { DirSourceBuilder dsb = new DirSourceBuilder(); dsb.hostName = string; - createWithDirSource(dsb.buildDirSource()); + return createWithDirSource(dsb.buildDirSource()); } private String address = "212.112.245.170"; - private static void createWithAddress(String string) { + private static RelayNetworkStatusConsensus + createWithAddress(String string) + throws DescriptorParseException { DirSourceBuilder dsb = new DirSourceBuilder(); dsb.address = string; - createWithDirSource(dsb.buildDirSource()); + return createWithDirSource(dsb.buildDirSource()); } private String dirPort = "80"; - private static void createWithDirPort(String string) { + private static RelayNetworkStatusConsensus + createWithDirPort(String string) + throws DescriptorParseException { DirSourceBuilder dsb = new DirSourceBuilder(); dsb.dirPort = string; - createWithDirSource(dsb.buildDirSource()); + return createWithDirSource(dsb.buildDirSource()); } private String orPort = "443"; - private static void createWithOrPort(String string) { + private static RelayNetworkStatusConsensus + createWithOrPort(String string) + throws DescriptorParseException { DirSourceBuilder dsb = new DirSourceBuilder(); dsb.orPort = string; - createWithDirSource(dsb.buildDirSource()); + return createWithDirSource(dsb.buildDirSource()); } private String contactLine = "contact 4096R/C5AA446D Sebastian Hahn " + "tor@sebastianhahn.net"; - private static void createWithContactLine(String line) { + private static RelayNetworkStatusConsensus + createWithContactLine(String line) + throws DescriptorParseException { DirSourceBuilder dsb = new DirSourceBuilder(); dsb.contactLine = line; - createWithDirSource(dsb.buildDirSource()); + return createWithDirSource(dsb.buildDirSource()); } private String voteDigestLine = "vote-digest 0F398A5834D2C139E1D92310B09F814F243354D1"; - private static void createWithVoteDigestLine(String line) { + private static RelayNetworkStatusConsensus + createWithVoteDigestLine(String line) + throws DescriptorParseException { DirSourceBuilder dsb = new DirSourceBuilder(); dsb.voteDigestLine = line; - createWithDirSource(dsb.buildDirSource()); + return createWithDirSource(dsb.buildDirSource()); } private String buildDirSource() { StringBuilder sb = new StringBuilder(); @@ -294,76 +338,93 @@ public class RelayNetworkStatusConsensusImplTest { /* Helper class to build a status entry based on default data and * modifications requested by test methods. */ private static class StatusEntryBuilder { - private static void createWithStatusEntry(String statusEntryString) { + private static RelayNetworkStatusConsensus + createWithStatusEntry(String statusEntryString) + throws DescriptorParseException { ConsensusBuilder cb = new ConsensusBuilder(); cb.statusEntries.add(statusEntryString); - new RelayNetworkStatusConsensusImpl(cb.buildConsensus()); + return new RelayNetworkStatusConsensusImpl(cb.buildConsensus()); } private String nickname = "right2privassy3"; - private static void createWithNickname(String string) { + private static RelayNetworkStatusConsensus + createWithNickname(String string) + throws DescriptorParseException { StatusEntryBuilder seb = new StatusEntryBuilder(); seb.nickname = string; - createWithStatusEntry(seb.buildStatusEntry()); + return createWithStatusEntry(seb.buildStatusEntry()); } private String fingerprintBase64 = "ADQ6gCT3DiFHKPDFr3rODBUI8HM"; - private static void createWithFingerprintBase64(String string) { + private static RelayNetworkStatusConsensus + createWithFingerprintBase64(String string) + throws DescriptorParseException { StatusEntryBuilder seb = new StatusEntryBuilder(); seb.fingerprintBase64 = string; - createWithStatusEntry(seb.buildStatusEntry()); + return createWithStatusEntry(seb.buildStatusEntry()); } private String descriptorBase64 = "Yiti+nayuT2Efe2X1+M4nslwVuU"; - private static void createWithDescriptorBase64(String string) { + private static RelayNetworkStatusConsensus + createWithDescriptorBase64(String string) + throws DescriptorParseException { StatusEntryBuilder seb = new StatusEntryBuilder(); seb.descriptorBase64 = string; - createWithStatusEntry(seb.buildStatusEntry()); + return createWithStatusEntry(seb.buildStatusEntry()); } private String publishedString = "2011-11-29 21:34:27"; - private static void createWithPublishedString(String string) { + private static RelayNetworkStatusConsensus + createWithPublishedString(String string) + throws DescriptorParseException { StatusEntryBuilder seb = new StatusEntryBuilder(); seb.publishedString = string; - createWithStatusEntry(seb.buildStatusEntry()); + return createWithStatusEntry(seb.buildStatusEntry()); } private String address = "50.63.8.215"; - private static void createWithAddress(String string) { + private static RelayNetworkStatusConsensus + createWithAddress(String string) throws DescriptorParseException { StatusEntryBuilder seb = new StatusEntryBuilder(); seb.address = string; - createWithStatusEntry(seb.buildStatusEntry()); + return createWithStatusEntry(seb.buildStatusEntry()); } private String orPort = "9023"; - private static void createWithOrPort(String string) { + private static RelayNetworkStatusConsensus + createWithOrPort(String string) throws DescriptorParseException { StatusEntryBuilder seb = new StatusEntryBuilder(); seb.orPort = string; - createWithStatusEntry(seb.buildStatusEntry()); + return createWithStatusEntry(seb.buildStatusEntry()); } private String dirPort = "0"; - private static void createWithDirPort(String string) { + private static RelayNetworkStatusConsensus + createWithDirPort(String string) throws DescriptorParseException { StatusEntryBuilder seb = new StatusEntryBuilder(); seb.dirPort = string; - createWithStatusEntry(seb.buildStatusEntry()); + return createWithStatusEntry(seb.buildStatusEntry()); } private String sLine = "s Exit Fast Named Running Stable Valid"; - private static void createWithSLine(String line) { + private static RelayNetworkStatusConsensus + createWithSLine(String line) throws DescriptorParseException { StatusEntryBuilder seb = new StatusEntryBuilder(); seb.sLine = line; - createWithStatusEntry(seb.buildStatusEntry()); + return createWithStatusEntry(seb.buildStatusEntry()); } private String vLine = "v Tor 0.2.1.29 (r8e9b25e6c7a2e70c)"; - private static void createWithVLine(String line) { + private static RelayNetworkStatusConsensus + createWithVLine(String line) throws DescriptorParseException { StatusEntryBuilder seb = new StatusEntryBuilder(); seb.vLine = line; - createWithStatusEntry(seb.buildStatusEntry()); + return createWithStatusEntry(seb.buildStatusEntry()); } private String wLine = "w Bandwidth=1"; - private static void createWithWLine(String line) { + private static RelayNetworkStatusConsensus + createWithWLine(String line) throws DescriptorParseException { StatusEntryBuilder seb = new StatusEntryBuilder(); seb.wLine = line; - createWithStatusEntry(seb.buildStatusEntry()); + return createWithStatusEntry(seb.buildStatusEntry()); } private String pLine = "p accept 80,1194,1220,1293"; - private static void createWithPLine(String line) { + private static RelayNetworkStatusConsensus + createWithPLine(String line) throws DescriptorParseException { StatusEntryBuilder seb = new StatusEntryBuilder(); seb.pLine = line; - createWithStatusEntry(seb.buildStatusEntry()); + return createWithStatusEntry(seb.buildStatusEntry()); } private String buildStatusEntry() { StringBuilder sb = new StringBuilder(); @@ -393,24 +454,29 @@ public class RelayNetworkStatusConsensusImplTest { /* Helper class to build a directory signature based on default data and * modifications requested by test methods. */ private static class DirectorySignatureBuilder { - private static void createWithDirectorySignature( - String directorySignatureString) { + private static RelayNetworkStatusConsensus + createWithDirectorySignature(String directorySignatureString) + throws DescriptorParseException { ConsensusBuilder cb = new ConsensusBuilder(); cb.directorySignatures.add(directorySignatureString); - new RelayNetworkStatusConsensusImpl(cb.buildConsensus()); + return new RelayNetworkStatusConsensusImpl(cb.buildConsensus()); } private String identity = "ED03BB616EB2F60BEC80151114BB25CEF515B226"; - private static void createWithIdentity(String string) { + private static RelayNetworkStatusConsensus + createWithIdentity(String string) + throws DescriptorParseException { DirectorySignatureBuilder dsb = new DirectorySignatureBuilder(); dsb.identity = string; - createWithDirectorySignature(dsb.buildDirectorySignature()); + return createWithDirectorySignature(dsb.buildDirectorySignature()); } private String signingKey = "845CF1D0B370CA443A8579D18E7987E7E532F639"; - private static void createWithSigningKey(String string) { + private static RelayNetworkStatusConsensus + createWithSigningKey(String string) + throws DescriptorParseException { DirectorySignatureBuilder dsb = new DirectorySignatureBuilder(); dsb.signingKey = string; - createWithDirectorySignature(dsb.buildDirectorySignature()); + return createWithDirectorySignature(dsb.buildDirectorySignature()); } private String buildDirectorySignature() { String directorySignature = "directory-signature " + identity + " " @@ -426,505 +492,622 @@ public class RelayNetworkStatusConsensusImplTest { } }
- /* TODO We should check this. */ @Test() - public void testSampleConsensus() { + public void testSampleConsensus() throws DescriptorParseException { ConsensusBuilder cb = new ConsensusBuilder(); - new RelayNetworkStatusConsensusImpl(cb.buildConsensus()); + RelayNetworkStatusConsensus consensus = + new RelayNetworkStatusConsensusImpl(cb.buildConsensus()); + assertEquals(3, consensus.getNetworkStatusVersion()); + assertEquals(11, consensus.getConsensusMethod()); + assertEquals(1322643600000L, consensus.getValidAfterMillis()); + assertEquals(1322647200000L, consensus.getFreshUntilMillis()); + assertEquals(1322654400000L, consensus.getValidUntilMillis()); + assertEquals(300L, consensus.getVoteSeconds()); + assertEquals(300L, consensus.getDistSeconds()); + assertTrue(consensus.getRecommendedClientVersions().contains( + "0.2.3.8-alpha")); + assertTrue(consensus.getRecommendedServerVersions().contains( + "0.2.3.8-alpha")); + assertTrue(consensus.getKnownFlags().contains("Running")); + assertEquals(30000, (int) consensus.getConsensusParams().get( + "CircuitPriorityHalflifeMsec")); + assertEquals("86.59.21.38", consensus.getDirSourceEntries().get( + "14C131DFC5C6F93646BE72FA1401C02A8DF2E8B4").getIp()); + assertTrue(consensus.containsStatusEntry( + "00795A6E8D91C270FC23B30F388A495553E01894")); + assertEquals("188.177.149.216", consensus.getStatusEntry( + "00795A6E8D91C270FC23B30F388A495553E01894").getAddress()); + assertEquals("3509BA5A624403A905C74DA5C8A0CEC9E0D3AF86", + consensus.getDirectorySignatures().get( + "14C131DFC5C6F93646BE72FA1401C02A8DF2E8B4")); + assertEquals(285, (int) consensus.getBandwidthWeights().get("Wbd")); + } + + @Test(expected = DescriptorParseException.class) + public void testNetworkStatusVersionNoLine() + throws DescriptorParseException { + ConsensusBuilder.createWithNetworkStatusVersionLine(null); }
- /* TODO Throwing a RuntimeException here (and in most places below) is - * bad. Maybe we should define a DescriptorParseException. */ - @Test(expected = RuntimeException.class) - public void testNetworkStatusVersionNoLine() { - ConsensusBuilder.createWithNetworkStatusVersionLine(null); + @Test(expected = DescriptorParseException.class) + public void testNetworkStatusVersionNewLine() + throws DescriptorParseException { + ConsensusBuilder.createWithNetworkStatusVersionLine( + "network-status-version 3\n"); }
- @Test(expected = RuntimeException.class) - public void testNetworkStatusVersionPrefixLineAtChar() { + @Test(expected = DescriptorParseException.class) + public void testNetworkStatusVersionPrefixLineAtChar() + throws DescriptorParseException { ConsensusBuilder.createWithNetworkStatusVersionLine( "@consensus\nnetwork-status-version 3"); }
- /* TODO This doesn't break. Should it? */ - @Test() - public void testNetworkStatusVersionPrefixDirectoryFooter() { + @Test(expected = DescriptorParseException.class) + public void testNetworkStatusVersionPrefixLine() + throws DescriptorParseException { ConsensusBuilder.createWithNetworkStatusVersionLine( "directory-footer\nnetwork-status-version 3"); } - - @Test(expected = RuntimeException.class) - public void testNetworkStatusVersionPrefixLinePoundChar() { + + @Test(expected = DescriptorParseException.class) + public void testNetworkStatusVersionPrefixLinePoundChar() + throws DescriptorParseException { ConsensusBuilder.createWithNetworkStatusVersionLine( "#consensus\nnetwork-status-version 3"); } - - @Test(expected = RuntimeException.class) - public void testNetworkStatusVersionNoSpace() { + + @Test(expected = DescriptorParseException.class) + public void testNetworkStatusVersionNoSpace() + throws DescriptorParseException { ConsensusBuilder.createWithNetworkStatusVersionLine( "network-status-version"); }
- @Test(expected = RuntimeException.class) - public void testNetworkStatusVersionOneSpace() { + @Test(expected = DescriptorParseException.class) + public void testNetworkStatusVersionOneSpace() + throws DescriptorParseException { ConsensusBuilder.createWithNetworkStatusVersionLine( "network-status-version "); }
- /* TODO The parser should only accept version 3 and throw an Exception - * here. */ - @Test() - public void testNetworkStatusVersion42() { + @Test(expected = DescriptorParseException.class) + public void testNetworkStatusVersion42() + throws DescriptorParseException { ConsensusBuilder.createWithNetworkStatusVersionLine( "network-status-version 42"); }
- @Test(expected = RuntimeException.class) - public void testNetworkStatusVersionFourtyTwo() { + @Test(expected = DescriptorParseException.class) + public void testNetworkStatusVersionFourtyTwo() + throws DescriptorParseException { ConsensusBuilder.createWithNetworkStatusVersionLine( "network-status-version FourtyTwo"); }
- /* TODO Shouldn't this throw an exception? */ - @Test() - public void testVoteStatusNoLine() { + @Test(expected = DescriptorParseException.class) + public void testVoteStatusNoLine() throws DescriptorParseException { ConsensusBuilder.createWithVoteStatusLine(null); }
- @Test(expected = RuntimeException.class) - public void testVoteStatusNoSpace() { + @Test(expected = DescriptorParseException.class) + public void testNetworkStatusVersionSpaceBefore() + throws DescriptorParseException { + ConsensusBuilder.createWithNetworkStatusVersionLine( + " network-status-version 3"); + } + + @Test(expected = DescriptorParseException.class) + public void testVoteStatusSpaceBefore() throws DescriptorParseException { + ConsensusBuilder.createWithVoteStatusLine(" vote-status consensus"); + } + + @Test(expected = DescriptorParseException.class) + public void testVoteStatusNoSpace() throws DescriptorParseException { ConsensusBuilder.createWithVoteStatusLine("vote-status"); }
- @Test(expected = RuntimeException.class) - public void testVoteStatusOneSpace() { + @Test(expected = DescriptorParseException.class) + public void testVoteStatusOneSpace() throws DescriptorParseException { ConsensusBuilder.createWithVoteStatusLine("vote-status "); }
- /* TODO Should this be accepted or not? */ - @Test(expected = RuntimeException.class) - public void testVoteStatusConsensusOneSpace() { + @Test() + public void testVoteStatusConsensusOneSpace() + throws DescriptorParseException { ConsensusBuilder.createWithVoteStatusLine("vote-status consensus "); }
- @Test(expected = RuntimeException.class) - public void testVoteStatusVote() { + @Test(expected = DescriptorParseException.class) + public void testVoteStatusVote() throws DescriptorParseException { ConsensusBuilder.createWithVoteStatusLine("vote-status vote"); }
- @Test(expected = RuntimeException.class) - public void testVoteStatusTheMagicVoteStatus() { + @Test(expected = DescriptorParseException.class) + public void testVoteStatusTheMagicVoteStatus() + throws DescriptorParseException { ConsensusBuilder.createWithVoteStatusLine( "vote-status TheMagicVoteStatus"); }
- @Test(expected = RuntimeException.class) - public void testConsensusMethodNoLine() { + @Test(expected = DescriptorParseException.class) + public void testConsensusMethodNoLine() + throws DescriptorParseException { ConsensusBuilder.createWithConsensusMethodLine(null); }
- @Test(expected = RuntimeException.class) - public void testConsensusMethodNoSpace() { + @Test(expected = DescriptorParseException.class) + public void testConsensusMethodNoSpace() + throws DescriptorParseException { ConsensusBuilder.createWithConsensusMethodLine("consensus-method"); }
- @Test(expected = RuntimeException.class) - public void testConsensusMethodOneSpace() { + @Test(expected = DescriptorParseException.class) + public void testConsensusMethodOneSpace() + throws DescriptorParseException { ConsensusBuilder.createWithConsensusMethodLine("consensus-method "); }
- @Test(expected = RuntimeException.class) - public void testConsensusMethodEleven() { + @Test(expected = DescriptorParseException.class) + public void testConsensusMethodEleven() + throws DescriptorParseException { ConsensusBuilder.createWithConsensusMethodLine( "consensus-method eleven"); }
- /* TODO We shouldn't allow negative values here. */ - @Test() - public void testConsensusMethodMinusOne() { + @Test(expected = DescriptorParseException.class) + public void testConsensusMethodMinusOne() + throws DescriptorParseException { ConsensusBuilder.createWithConsensusMethodLine("consensus-method -1"); }
- @Test(expected = RuntimeException.class) - public void testConsensusMethodNinePeriod() { + @Test(expected = DescriptorParseException.class) + public void testConsensusMethodNinePeriod() + throws DescriptorParseException { ConsensusBuilder.createWithConsensusMethodLine("consensus-method " + "999999999999999999999999999999999999999999999999999999999999"); }
- @Test(expected = RuntimeException.class) - public void testValidAfterNoLine() { + @Test(expected = DescriptorParseException.class) + public void testConsensusMethodTwoLines() + throws DescriptorParseException { + ConsensusBuilder.createWithConsensusMethodLine( + "consensus-method 1\nconsensus-method 1"); + } + + @Test(expected = DescriptorParseException.class) + public void testValidAfterNoLine() throws DescriptorParseException { ConsensusBuilder.createWithValidAfterLine(null); }
- @Test(expected = RuntimeException.class) - public void testValidAfterNoSpace() { + @Test(expected = DescriptorParseException.class) + public void testValidAfterNoSpace() throws DescriptorParseException { ConsensusBuilder.createWithValidAfterLine("valid-after"); }
- @Test(expected = RuntimeException.class) - public void testValidAfterOneSpace() { + @Test(expected = DescriptorParseException.class) + public void testValidAfterOneSpace() throws DescriptorParseException { ConsensusBuilder.createWithValidAfterLine("valid-after "); }
- @Test(expected = RuntimeException.class) - public void testValidAfterLongAgo() { + @Test(expected = DescriptorParseException.class) + public void testValidAfterLongAgo() throws DescriptorParseException { ConsensusBuilder.createWithValidAfterLine("valid-after long ago"); }
- /* TODO Wow, this should really throw an exception! */ - @Test() - public void testValidAfterFeb30() { + @Test(expected = DescriptorParseException.class) + public void testValidAfterFeb30() throws DescriptorParseException { ConsensusBuilder.createWithValidAfterLine( "valid-after 2011-02-30 09:00:00"); }
- @Test(expected = RuntimeException.class) - public void testFreshUntilNoLine() { + @Test(expected = DescriptorParseException.class) + public void testFreshUntilNoLine() throws DescriptorParseException { ConsensusBuilder.createWithFreshUntilLine(null); }
- @Test(expected = RuntimeException.class) - public void testFreshUntilAroundTen() { + @Test(expected = DescriptorParseException.class) + public void testFreshUntilAroundTen() throws DescriptorParseException { ConsensusBuilder.createWithFreshUntilLine( "fresh-until 2011-11-30 around ten"); }
- @Test(expected = RuntimeException.class) - public void testValidUntilTomorrowMorning() { + @Test(expected = DescriptorParseException.class) + public void testValidUntilTomorrowMorning() + throws DescriptorParseException { ConsensusBuilder.createWithValidUntilLine( "valid-until tomorrow morning"); }
- @Test(expected = RuntimeException.class) - public void testVotingDelayNoLine() { + @Test(expected = DescriptorParseException.class) + public void testVotingDelayNoLine() throws DescriptorParseException { ConsensusBuilder.createWithVotingDelayLine(null); }
- @Test(expected = RuntimeException.class) - public void testVotingDelayNoSpace() { + @Test(expected = DescriptorParseException.class) + public void testVotingDelayNoSpace() throws DescriptorParseException { ConsensusBuilder.createWithVotingDelayLine("voting-delay"); }
- @Test(expected = RuntimeException.class) - public void testVotingDelayOneSpace() { + @Test(expected = DescriptorParseException.class) + public void testVotingDelayOneSpace() throws DescriptorParseException { ConsensusBuilder.createWithVotingDelayLine("voting-delay "); }
- /* TODO This should throw an exception. */ - @Test() - public void testVotingDelayTriple() { + @Test(expected = DescriptorParseException.class) + public void testVotingDelayTriple() throws DescriptorParseException { ConsensusBuilder.createWithVotingDelayLine( "voting-delay 300 300 300"); }
- /* TODO This should throw an exception. */ - @Test() - public void testVotingDelaySingle() { + @Test(expected = DescriptorParseException.class) + public void testVotingDelaySingle() throws DescriptorParseException { ConsensusBuilder.createWithVotingDelayLine("voting-delay 300"); }
- @Test(expected = RuntimeException.class) - public void testVotingDelayOneTwo() { + @Test(expected = DescriptorParseException.class) + public void testVotingDelayOneTwo() throws DescriptorParseException { ConsensusBuilder.createWithVotingDelayLine("voting-delay one two"); }
- /* TODO Should this be forbidden? */ @Test() - public void testClientVersionsNoLineServerVersionsNoLine() { + public void testClientServerVersionsNoLine() + throws DescriptorParseException { ConsensusBuilder cb = new ConsensusBuilder(); cb.clientVersionsLine = null; cb.serverVersionsLine = null; - new RelayNetworkStatusConsensusImpl(cb.buildConsensus()); + RelayNetworkStatusConsensus consensus = + new RelayNetworkStatusConsensusImpl(cb.buildConsensus()); + assertNull(consensus.getRecommendedClientVersions()); + assertNull(consensus.getRecommendedServerVersions()); }
- /* TODO Should this be forbidden? */ @Test() - public void testServerVersionsNoLine() { - ConsensusBuilder.createWithServerVersionsLine(null); + public void testServerVersionsNoLine() throws DescriptorParseException { + RelayNetworkStatusConsensus consensus = + ConsensusBuilder.createWithServerVersionsLine(null); + assertNotNull(consensus.getRecommendedClientVersions()); + assertNull(consensus.getRecommendedServerVersions()); }
- /* TODO Should this be forbidden? */ @Test() - public void testClientVersionsNoLine() { - ConsensusBuilder.createWithClientVersionsLine(null); + public void testClientVersionsNoLine() throws DescriptorParseException { + RelayNetworkStatusConsensus consensus = + ConsensusBuilder.createWithClientVersionsLine(null); + assertNull(consensus.getRecommendedClientVersions()); + assertNotNull(consensus.getRecommendedServerVersions()); }
- @Test(expected = RuntimeException.class) - public void testClientVersionsNoSpace() { - ConsensusBuilder.createWithClientVersionsLine("client-versions"); + @Test() + public void testClientVersionsNoSpace() + throws DescriptorParseException { + RelayNetworkStatusConsensus consensus = + ConsensusBuilder.createWithClientVersionsLine("client-versions"); + assertNotNull(consensus.getRecommendedClientVersions()); + assertTrue(consensus.getRecommendedClientVersions().isEmpty()); }
- @Test(expected = RuntimeException.class) - public void testClientVersionsOneSpace() { - ConsensusBuilder.createWithClientVersionsLine("client-versions "); + @Test() + public void testClientVersionsOneSpace() + throws DescriptorParseException { + RelayNetworkStatusConsensus consensus = + ConsensusBuilder.createWithClientVersionsLine("client-versions "); + assertNotNull(consensus.getRecommendedClientVersions()); + assertTrue(consensus.getRecommendedClientVersions().isEmpty()); }
- /* TODO This should be caught. */ - @Test() - public void testClientVersionsComma() { + @Test(expected = DescriptorParseException.class) + public void testClientVersionsComma() throws DescriptorParseException { ConsensusBuilder.createWithClientVersionsLine("client-versions ,"); }
- /* TODO This should be caught. */ - @Test() - public void testClientVersionsCommaVersion() { + @Test(expected = DescriptorParseException.class) + public void testClientVersionsCommaVersion() + throws DescriptorParseException { ConsensusBuilder.createWithClientVersionsLine( "client-versions ,0.2.2.34"); }
- @Test(expected = RuntimeException.class) - public void testKnownFlagsNoLine() { + @Test(expected = DescriptorParseException.class) + public void testKnownFlagsNoLine() throws DescriptorParseException { ConsensusBuilder.createWithKnownFlagsLine(null); }
- @Test(expected = RuntimeException.class) - public void testKnownFlagsNoSpace() { + @Test(expected = DescriptorParseException.class) + public void testKnownFlagsNoSpace() throws DescriptorParseException { ConsensusBuilder.createWithKnownFlagsLine("known-flags"); }
- /* TODO Looks like this okay, right? */ - @Test() - public void testKnownFlagsOneSpace() { + @Test(expected = DescriptorParseException.class) + public void testKnownFlagsOneSpace() throws DescriptorParseException { ConsensusBuilder.createWithKnownFlagsLine("known-flags "); }
- /* TODO Make sure that the params line is optional. */ @Test() - public void testParamsNoLine() { - ConsensusBuilder.createWithParamsLine(null); + public void testParamsNoLine() throws DescriptorParseException { + RelayNetworkStatusConsensus consensus = + ConsensusBuilder.createWithParamsLine(null); + assertNull(consensus.getConsensusParams()); }
- /* TODO If it's okay to provide an empty params line, this one should be - * accepted, too. */ - @Test(expected = RuntimeException.class) - public void testParamsNoSpace() { - ConsensusBuilder.createWithParamsLine("params"); + @Test() + public void testParamsNoSpace() throws DescriptorParseException { + RelayNetworkStatusConsensus consensus = + ConsensusBuilder.createWithParamsLine("params"); + assertNotNull(consensus.getConsensusParams()); + assertTrue(consensus.getConsensusParams().isEmpty()); }
- /* TODO Is this okay? */ @Test() - public void testParamsOneSpace() { - ConsensusBuilder.createWithParamsLine("params "); + public void testParamsOneSpace() throws DescriptorParseException { + RelayNetworkStatusConsensus consensus = + ConsensusBuilder.createWithParamsLine("params "); + assertNotNull(consensus.getConsensusParams()); + assertTrue(consensus.getConsensusParams().isEmpty()); }
- /* TODO Hmm, and this is okay? */ @Test() - public void testParamsThreeSpaces() { - ConsensusBuilder.createWithParamsLine("params "); + public void testParamsThreeSpaces() throws DescriptorParseException { + RelayNetworkStatusConsensus consensus = + ConsensusBuilder.createWithParamsLine("params "); + assertNotNull(consensus.getConsensusParams()); + assertTrue(consensus.getConsensusParams().isEmpty()); }
- /* TODO The error message here looked strange. Investigate. */ - @Test(expected = RuntimeException.class) - public void testParamsNoEqualSign() { + @Test(expected = DescriptorParseException.class) + public void testParamsNoEqualSign() throws DescriptorParseException { ConsensusBuilder.createWithParamsLine("params key-value"); }
- /* TODO We should check this. */ + @Test(expected = DescriptorParseException.class) + public void testParamsOneTooLargeNegative() + throws DescriptorParseException { + ConsensusBuilder.createWithParamsLine("params min=-2147483649"); + } + @Test() - public void testDirSourceIdentityTooShort() { - DirSourceBuilder.createWithIdentity("ED03BB616EB2F60BEC8015111"); + public void testParamsLargestNegative() + throws DescriptorParseException { + RelayNetworkStatusConsensus consensus = + ConsensusBuilder.createWithParamsLine("params min=-2147483648"); + assertEquals(1, consensus.getConsensusParams().size()); + assertEquals(-2147483648, + (int) consensus.getConsensusParams().get("min")); + } + + @Test() + public void testParamsLargestPositive() + throws DescriptorParseException { + RelayNetworkStatusConsensus consensus = + ConsensusBuilder.createWithParamsLine("params max=2147483647"); + assertEquals(1, consensus.getConsensusParams().size()); + assertEquals(2147483647, + (int) consensus.getConsensusParams().get("max")); + } + + @Test(expected = DescriptorParseException.class) + public void testParamsOneTooLargePositive() + throws DescriptorParseException { + ConsensusBuilder.createWithParamsLine("params max=2147483648"); }
- /* TODO We should check this. */ @Test() - public void testDirSourceIdentityTooLong() { + public void testDirSourceLegacyNickname() + throws DescriptorParseException { + DirSourceBuilder dsb = new DirSourceBuilder(); + dsb.nickname = "gabelmoo-legacy"; + dsb.identity = "81349FC1F2DBA2C2C11B45CB9706637D480AB913"; + dsb.contactLine = null; + dsb.voteDigestLine = null; + RelayNetworkStatusConsensus consensus = + DirSourceBuilder.createWithDirSource(dsb.buildDirSource()); + assertEquals(3, consensus.getDirSourceEntries().size()); + assertTrue(consensus.getDirSourceEntries().get( + "81349FC1F2DBA2C2C11B45CB9706637D480AB913").isLegacy()); + } + + @Test(expected = DescriptorParseException.class) + public void testDirSourceIdentityTooShort() + throws DescriptorParseException { + DirSourceBuilder.createWithIdentity("ED03BB616EB2F60BEC8015111"); + } + + @Test(expected = DescriptorParseException.class) + public void testDirSourceIdentityTooLong() + throws DescriptorParseException { DirSourceBuilder.createWithIdentity("ED03BB616EB2F60BEC8015111" + "4BB25CEF515B226ED03BB616EB2F60BEC8"); }
- /* TODO We should check this. */ - @Test() - public void testDirSourceAddress24() { + @Test(expected = DescriptorParseException.class) + public void testDirSourceAddress24() throws DescriptorParseException { DirSourceBuilder.createWithAddress("212.112.245"); }
- /* TODO We should check this. */ - @Test() - public void testDirSourceAddress40() { + @Test(expected = DescriptorParseException.class) + public void testDirSourceAddress40() throws DescriptorParseException { DirSourceBuilder.createWithAddress("212.112.245.170.123"); }
- /* TODO We should check this. */ - @Test() - public void testDirSourceDirPortMinusOne() { + @Test(expected = DescriptorParseException.class) + public void testDirSourceDirPortMinusOne() + throws DescriptorParseException { DirSourceBuilder.createWithDirPort("-1"); }
- /* TODO We should check this. */ - @Test() - public void testDirSourceDirPort66666() { + @Test(expected = DescriptorParseException.class) + public void testDirSourceDirPort66666() + throws DescriptorParseException { DirSourceBuilder.createWithDirPort("66666"); }
- /* TODO We should check this. */ - @Test(expected = RuntimeException.class) - public void testDirSourceDirPortOnions() { + @Test(expected = DescriptorParseException.class) + public void testDirSourceDirPortOnions() + throws DescriptorParseException { DirSourceBuilder.createWithDirPort("onions"); }
- /* TODO We should check this. */ - @Test(expected = RuntimeException.class) - public void testDirSourceOrPortOnions() { + @Test(expected = DescriptorParseException.class) + public void testDirSourceOrPortOnions() + throws DescriptorParseException { DirSourceBuilder.createWithOrPort("onions"); }
- /* TODO We should check this. */ @Test() - public void testDirSourceContactNoLine() { - DirSourceBuilder.createWithContactLine(null); + public void testDirSourceContactNoLine() + throws DescriptorParseException { + RelayNetworkStatusConsensus consensus = + DirSourceBuilder.createWithContactLine(null); + assertNull(consensus.getDirSourceEntries().get( + "ED03BB616EB2F60BEC80151114BB25CEF515B226").getContactLine()); }
- /* TODO We should check this. */ - @Test(expected = RuntimeException.class) - public void testDirSourceContactLineNoSpace() { - DirSourceBuilder.createWithContactLine("contact"); + @Test() + public void testDirSourceContactLineNoSpace() + throws DescriptorParseException { + RelayNetworkStatusConsensus consensus = + DirSourceBuilder.createWithContactLine("contact"); + assertNotNull(consensus.getDirSourceEntries().get( + "ED03BB616EB2F60BEC80151114BB25CEF515B226").getContactLine()); }
- /* TODO We should check this. */ @Test() - public void testDirSourceContactLineOneSpace() { - DirSourceBuilder.createWithContactLine("contact "); + public void testDirSourceContactLineOneSpace() + throws DescriptorParseException { + RelayNetworkStatusConsensus consensus = + DirSourceBuilder.createWithContactLine("contact "); + assertNotNull(consensus.getDirSourceEntries().get( + "ED03BB616EB2F60BEC80151114BB25CEF515B226").getContactLine()); }
- /* TODO We should check this. */ - @Test() - public void testDirSourceVoteDigestNoLine() { + @Test(expected = DescriptorParseException.class) + public void testDirSourceVoteDigestNoLine() + throws DescriptorParseException { DirSourceBuilder.createWithVoteDigestLine(null); }
- /* TODO We should check this. */ - @Test(expected = RuntimeException.class) - public void testDirSourceVoteDigestLineNoSpace() { + @Test(expected = DescriptorParseException.class) + public void testDirSourceVoteDigestLineNoSpace() + throws DescriptorParseException { DirSourceBuilder.createWithVoteDigestLine("vote-digest"); }
- /* TODO We should check this. */ - @Test(expected = RuntimeException.class) - public void testDirSourceVoteDigestLineOneSpace() { + @Test(expected = DescriptorParseException.class) + public void testDirSourceVoteDigestLineOneSpace() + throws DescriptorParseException { DirSourceBuilder.createWithVoteDigestLine("vote-digest "); }
- /* TODO We should check this. */ - @Test() - public void testNicknameNotAllowedChars() { + @Test(expected = DescriptorParseException.class) + public void testNicknameNotAllowedChars() + throws DescriptorParseException { StatusEntryBuilder.createWithNickname("notAll()wed"); }
- /* TODO We should check this. */ - @Test() - public void testNicknameTooLong() { + @Test(expected = DescriptorParseException.class) + public void testNicknameTooLong() throws DescriptorParseException { StatusEntryBuilder.createWithNickname("1234567890123456789tooLong"); }
- /* TODO We should check this. */ - @Test() - public void testFingerprintTooShort() { + @Test(expected = DescriptorParseException.class) + public void testFingerprintTooShort() throws DescriptorParseException { StatusEntryBuilder.createWithFingerprintBase64("TooShort"); }
- /* TODO We should check this. */ - @Test() - public void testFingerprintEndsWithEqualSign() { + @Test(expected = DescriptorParseException.class) + public void testFingerprintEndsWithEqualSign() + throws DescriptorParseException { StatusEntryBuilder.createWithFingerprintBase64( "ADQ6gCT3DiFHKPDFr3rODBUI8H="); }
- /* TODO We should check this. */ - @Test() - public void testFingerprintTooLong() { + @Test(expected = DescriptorParseException.class) + public void testFingerprintTooLong() throws DescriptorParseException { StatusEntryBuilder.createWithFingerprintBase64( "ADQ6gCT3DiFHKPDFr3rODBUI8HMAAAA"); }
- /* TODO We should check this. */ - @Test() - public void testDescriptorTooShort() { + @Test(expected = DescriptorParseException.class) + public void testDescriptorTooShort() throws DescriptorParseException { StatusEntryBuilder.createWithDescriptorBase64("TooShort"); }
- /* TODO We should check this. */ - @Test() - public void testDescriptorEndsWithEqualSign() { + @Test(expected = DescriptorParseException.class) + public void testDescriptorEndsWithEqualSign() + throws DescriptorParseException { StatusEntryBuilder.createWithDescriptorBase64( "ADQ6gCT3DiFHKPDFr3rODBUI8H="); }
- /* TODO We should check this. */ - @Test() - public void testDescriptorTooLong() { + @Test(expected = DescriptorParseException.class) + public void testDescriptorTooLong() throws DescriptorParseException { StatusEntryBuilder.createWithDescriptorBase64( "Yiti+nayuT2Efe2X1+M4nslwVuUAAAA"); }
- /* TODO We should check this. */ - @Test() - public void testPublished1960() { + @Test(expected = DescriptorParseException.class) + public void testPublished1960() throws DescriptorParseException { StatusEntryBuilder.createWithPublishedString("1960-11-29 21:34:27"); }
- /* TODO We should check this. */ - @Test() - public void testPublished9999() { + @Test(expected = DescriptorParseException.class) + public void testPublished9999() throws DescriptorParseException { StatusEntryBuilder.createWithPublishedString("9999-11-29 21:34:27"); }
- /* TODO We should check this. */ - @Test() - public void testAddress256() { + @Test(expected = DescriptorParseException.class) + public void testAddress256() throws DescriptorParseException { StatusEntryBuilder.createWithAddress("256.63.8.215"); }
- /* TODO We should check this. */ - @Test() - public void testAddress24() { + @Test(expected = DescriptorParseException.class) + public void testAddress24() throws DescriptorParseException { StatusEntryBuilder.createWithAddress("50.63.8/24"); }
- /* TODO We should check this. */ - @Test() - public void testAddressV6() { + @Test(expected = DescriptorParseException.class) + public void testAddressV6() throws DescriptorParseException { StatusEntryBuilder.createWithAddress("::1"); }
- /* TODO We should check this. */ - @Test() - public void testOrPort66666() { + @Test(expected = DescriptorParseException.class) + public void testOrPort66666() throws DescriptorParseException { StatusEntryBuilder.createWithOrPort("66666"); }
- /* TODO We should check this. */ - @Test() - public void testOrPortEighty() { + @Test(expected = DescriptorParseException.class) + public void testOrPortEighty() throws DescriptorParseException { StatusEntryBuilder.createWithOrPort("eighty"); }
- /* TODO We should check this. */ - @Test() - public void testDirPortMinusOne() { + @Test(expected = DescriptorParseException.class) + public void testDirPortMinusOne() throws DescriptorParseException { StatusEntryBuilder.createWithDirPort("-1"); }
- /* TODO We should check this. */ - @Test() - public void testDirPortZero() { + @Test(expected = DescriptorParseException.class) + public void testDirPortZero() throws DescriptorParseException { StatusEntryBuilder.createWithDirPort("zero"); }
- /* TODO We should check this. */ @Test() - public void testSLineNoSpace() { - StatusEntryBuilder.createWithSLine("s"); + public void testSLineNoSpace() throws DescriptorParseException { + RelayNetworkStatusConsensus consensus = + StatusEntryBuilder.createWithSLine("s"); + assertTrue(consensus.getStatusEntry( + "00343A8024F70E214728F0C5AF7ACE0C1508F073").getFlags().isEmpty()); }
- /* TODO We should check this. */ @Test() - public void testSLineOneSpace() { - StatusEntryBuilder.createWithSLine("s "); + public void testSLineOneSpace() throws DescriptorParseException { + RelayNetworkStatusConsensus consensus = + StatusEntryBuilder.createWithSLine("s "); + assertTrue(consensus.getStatusEntry( + "00343A8024F70E214728F0C5AF7ACE0C1508F073").getFlags().isEmpty()); }
- /* TODO We should detect this. */ - @Test() - public void testTwoSLines() { + @Test(expected = DescriptorParseException.class) + public void testTwoSLines() throws DescriptorParseException { StatusEntryBuilder sb = new StatusEntryBuilder(); sb.sLine = sb.sLine + "\n" + sb.sLine; ConsensusBuilder cb = new ConsensusBuilder(); @@ -932,27 +1115,23 @@ public class RelayNetworkStatusConsensusImplTest { new RelayNetworkStatusConsensusImpl(cb.buildConsensus()); }
- /* TODO This is not allowed, right? */ - @Test(expected = RuntimeException.class) - public void testWLineNoSpace() { - StatusEntryBuilder.createWithSLine("w"); + @Test(expected = DescriptorParseException.class) + public void testWLineNoSpace() throws DescriptorParseException { + StatusEntryBuilder.createWithWLine("w"); }
- /* TODO We should check this. */ - @Test() - public void testWLineOneSpace() { - StatusEntryBuilder.createWithSLine("w "); + @Test(expected = DescriptorParseException.class) + public void testWLineOneSpace() throws DescriptorParseException { + StatusEntryBuilder.createWithWLine("w "); }
- /* TODO We should check this. */ - @Test() - public void testWLineWarpSeven() { + @Test(expected = DescriptorParseException.class) + public void testWLineWarpSeven() throws DescriptorParseException { StatusEntryBuilder.createWithWLine("w Warp=7"); }
- /* TODO We should detect this. */ - @Test() - public void testTwoWLines() { + @Test(expected = DescriptorParseException.class) + public void testTwoWLines() throws DescriptorParseException { StatusEntryBuilder sb = new StatusEntryBuilder(); sb.wLine = sb.wLine + "\n" + sb.wLine; ConsensusBuilder cb = new ConsensusBuilder(); @@ -960,33 +1139,28 @@ public class RelayNetworkStatusConsensusImplTest { new RelayNetworkStatusConsensusImpl(cb.buildConsensus()); }
- /* TODO We should check this. */ - @Test() - public void testPLineNoPolicy() { + @Test(expected = DescriptorParseException.class) + public void testPLineNoPolicy() throws DescriptorParseException { StatusEntryBuilder.createWithPLine("p 80"); }
- /* TODO We should check this. */ - @Test() - public void testPLineNoPorts() { + @Test(expected = DescriptorParseException.class) + public void testPLineNoPorts() throws DescriptorParseException { StatusEntryBuilder.createWithPLine("p accept"); }
- /* TODO We should check this. */ - @Test() - public void testPLineNoPolicyNoPorts() { + @Test(expected = DescriptorParseException.class) + public void testPLineNoPolicyNoPorts() throws DescriptorParseException { StatusEntryBuilder.createWithPLine("p "); }
- /* TODO We should check this. */ - @Test() - public void testPLineProject() { + @Test(expected = DescriptorParseException.class) + public void testPLineProject() throws DescriptorParseException { StatusEntryBuilder.createWithPLine("p project 80"); }
- /* TODO We should detect this. */ - @Test() - public void testTwoPLines() { + @Test(expected = DescriptorParseException.class) + public void testTwoPLines() throws DescriptorParseException { StatusEntryBuilder sb = new StatusEntryBuilder(); sb.pLine = sb.pLine + "\n" + sb.pLine; ConsensusBuilder cb = new ConsensusBuilder(); @@ -994,86 +1168,96 @@ public class RelayNetworkStatusConsensusImplTest { new RelayNetworkStatusConsensusImpl(cb.buildConsensus()); }
- /* TODO Should we allow this? */ - @Test(expected = RuntimeException.class) - public void testNoStatusEntries() { + @Test() + public void testNoStatusEntries() throws DescriptorParseException { ConsensusBuilder cb = new ConsensusBuilder(); cb.statusEntries.clear(); - new RelayNetworkStatusConsensusImpl(cb.buildConsensus()); + RelayNetworkStatusConsensus consensus = + new RelayNetworkStatusConsensusImpl(cb.buildConsensus()); + assertFalse(consensus.containsStatusEntry( + "00795A6E8D91C270FC23B30F388A495553E01894")); }
- /* TODO Why does this not break? Ah, maybe it just leaves out one - * status entry. Ugh. It should break! */ - @Test() - public void testDirectoryFooterNoLine() { + @Test(expected = DescriptorParseException.class) + public void testDirectoryFooterNoLine() + throws DescriptorParseException { ConsensusBuilder.createWithDirectoryFooterLine(null); }
- @Test(expected = RuntimeException.class) - public void testDirectoryFooterLineSpace() { + @Test() + public void testDirectoryFooterLineSpace() + throws DescriptorParseException { ConsensusBuilder.createWithDirectoryFooterLine("directory-footer "); }
- /* TODO Make sure that this is really okay in the code. */ @Test() - public void testBandwidthWeightsNoLine() { - ConsensusBuilder.createWithBandwidthWeightsLine(null); + public void testBandwidthWeightsNoLine() + throws DescriptorParseException { + RelayNetworkStatusConsensus consensus = + ConsensusBuilder.createWithBandwidthWeightsLine(null); + assertNull(consensus.getBandwidthWeights()); }
- @Test(expected = RuntimeException.class) - public void testBandwidthWeightsLineNoSpace() { - ConsensusBuilder.createWithBandwidthWeightsLine("bandwidth-weights"); + @Test() + public void testBandwidthWeightsLineNoSpace() + throws DescriptorParseException { + RelayNetworkStatusConsensus consensus = ConsensusBuilder. + createWithBandwidthWeightsLine("bandwidth-weights"); + assertNotNull(consensus.getBandwidthWeights()); }
- /* TODO We should check this. */ @Test() - public void testBandwidthWeightsLineOneSpace() { - ConsensusBuilder.createWithBandwidthWeightsLine("bandwidth-weights "); + public void testBandwidthWeightsLineOneSpace() + throws DescriptorParseException { + RelayNetworkStatusConsensus consensus = ConsensusBuilder. + createWithBandwidthWeightsLine("bandwidth-weights "); + assertNotNull(consensus.getBandwidthWeights()); }
- /* TODO We should check this. */ - @Test() - public void testBandwidthWeightsLineNoEqualSign() { + @Test(expected = DescriptorParseException.class) + public void testBandwidthWeightsLineNoEqualSign() + throws DescriptorParseException { ConsensusBuilder.createWithBandwidthWeightsLine( "bandwidth-weights Wbd-285"); }
- /* TODO We should check this. */ - @Test() - public void testDirectorySignatureIdentityTooShort() { + @Test(expected = DescriptorParseException.class) + public void testDirectorySignatureIdentityTooShort() + throws DescriptorParseException { DirectorySignatureBuilder.createWithIdentity("ED03BB616EB2F60"); }
- /* TODO We should check this. */ - @Test() - public void testDirectorySignatureIdentityTooLong() { + @Test(expected = DescriptorParseException.class) + public void testDirectorySignatureIdentityTooLong() + throws DescriptorParseException { DirectorySignatureBuilder.createWithIdentity( "ED03BB616EB2F60BEC80151114BB25CEF515B226ED03BB616EB2F60BEC"); }
- /* TODO We should check this. */ - @Test() - public void testDirectorySignatureSigningKeyTooShort() { + @Test(expected = DescriptorParseException.class) + public void testDirectorySignatureSigningKeyTooShort() + throws DescriptorParseException { DirectorySignatureBuilder.createWithSigningKey("845CF1D0B370CA4"); }
- /* TODO We should check this. */ - @Test() - public void testDirectorySignatureSigningKeyTooLong() { + @Test(expected = DescriptorParseException.class) + public void testDirectorySignatureSigningKeyTooLong() + throws DescriptorParseException { DirectorySignatureBuilder.createWithSigningKey( "845CF1D0B370CA443A8579D18E7987E7E532F639845CF1D0B370CA443A"); }
- @Test(expected = RuntimeException.class) - public void testNonAsciiByte20() { + @Test(expected = DescriptorParseException.class) + public void testNonAsciiByte20() throws DescriptorParseException { ConsensusBuilder cb = new ConsensusBuilder(); byte[] consensusBytes = cb.buildConsensus(); consensusBytes[20] = (byte) 200; new RelayNetworkStatusConsensusImpl(consensusBytes); }
- @Test(expected = RuntimeException.class) - public void testNonAsciiByteMinusOne() { + @Test(expected = DescriptorParseException.class) + public void testNonAsciiByteMinusOne() + throws DescriptorParseException { ConsensusBuilder cb = new ConsensusBuilder(); cb.networkStatusVersionLine = "Xnetwork-status-version 3"; byte[] consensusBytes = cb.buildConsensus();
tor-commits@lists.torproject.org