[tor-commits] [metrics-lib/master] Make consensus parsing a lot more robust.
karsten at torproject.org
karsten at torproject.org
Wed Dec 14 18:18:00 UTC 2011
commit 228d6564f8e7b6bec635216d64282423f407025a
Author: Karsten Loesing <karsten.loesing at 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 at 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();
More information about the tor-commits
mailing list