[Author Prev][Author Next][Thread Prev][Thread Next][Author Index][Thread Index]
[tor-commits] [metrics-lib/master] Make votes use the general network-status parsing code.
commit cb9c62a90e30052db5599bc469da95de161af087
Author: Karsten Loesing <karsten.loesing@xxxxxxx>
Date: Thu Dec 15 20:45:42 2011 +0100
Make votes use the general network-status parsing code.
---
.../descriptor/RelayNetworkStatusVote.java | 11 +-
.../descriptor/impl/NetworkStatusImpl.java | 20 +-
.../impl/RelayNetworkStatusVoteImpl.java | 577 ++++++++++++--------
.../impl/RelayNetworkStatusVoteImplTest.java | 574 +++++++++++++++++++
4 files changed, 933 insertions(+), 249 deletions(-)
diff --git a/src/org/torproject/descriptor/RelayNetworkStatusVote.java b/src/org/torproject/descriptor/RelayNetworkStatusVote.java
index 6bfdd6f..aab90bd 100644
--- a/src/org/torproject/descriptor/RelayNetworkStatusVote.java
+++ b/src/org/torproject/descriptor/RelayNetworkStatusVote.java
@@ -27,8 +27,11 @@ public interface RelayNetworkStatusVote 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 authority doesn't
* recommend server versions. */
@@ -65,6 +68,10 @@ public interface RelayNetworkStatusVote extends Descriptor {
/* Return the directory key certificate version. */
public int getDirKeyCertificateVersion();
+ /* Return the legacy key or null if the directory authority does not use
+ * a legacy key. */
+ public String getLegacyKey();
+
/* Return the directory key publication timestamp. */
public long getDirKeyPublishedMillis();
diff --git a/src/org/torproject/descriptor/impl/NetworkStatusImpl.java b/src/org/torproject/descriptor/impl/NetworkStatusImpl.java
index 6ca546e..af8b9e2 100644
--- a/src/org/torproject/descriptor/impl/NetworkStatusImpl.java
+++ b/src/org/torproject/descriptor/impl/NetworkStatusImpl.java
@@ -51,6 +51,7 @@ public abstract class NetworkStatusImpl {
protected NetworkStatusImpl(byte[] rawDescriptorBytes)
throws DescriptorParseException {
this.rawDescriptorBytes = rawDescriptorBytes;
+ this.countKeywords(rawDescriptorBytes);
this.splitAndParseParts(rawDescriptorBytes);
}
@@ -126,7 +127,6 @@ public abstract class NetworkStatusImpl {
System.arraycopy(this.rawDescriptorBytes, start,
headerBytes, 0, end - start);
this.rememberFirstKeyword(headerBytes);
- this.countKeywords(headerBytes);
this.parseHeader(headerBytes);
}
@@ -153,7 +153,6 @@ public abstract class NetworkStatusImpl {
byte[] directoryFooterBytes = new byte[end - start];
System.arraycopy(this.rawDescriptorBytes, start,
directoryFooterBytes, 0, end - start);
- this.countKeywords(directoryFooterBytes);
this.parseFooter(directoryFooterBytes);
}
@@ -264,17 +263,17 @@ public abstract class NetworkStatusImpl {
* subclasses. */
private Map<String, Integer> parsedKeywords =
new HashMap<String, Integer>();
- protected void countKeywords(byte[] headerOrFooterBytes)
+ protected void countKeywords(byte[] rawDescriptorBytes)
throws DescriptorParseException {
try {
BufferedReader br = new BufferedReader(new StringReader(
- new String(headerOrFooterBytes)));
+ new String(rawDescriptorBytes)));
String line;
boolean skipCrypto = false;
while ((line = br.readLine()) != null) {
if (line.startsWith("-----BEGIN")) {
skipCrypto = true;
- } else if (line.equals("-----END")) {
+ } else if (line.startsWith("-----END")) {
skipCrypto = false;
} else if (!skipCrypto) {
String keyword = line.split(" ", -1)[0];
@@ -299,11 +298,14 @@ public abstract class NetworkStatusImpl {
protected void checkExactlyOnceKeywords(Set<String> keywords)
throws DescriptorParseException {
for (String keyword : keywords) {
- if (!this.parsedKeywords.containsKey(keyword) ||
- this.parsedKeywords.get(keyword) != 1) {
+ int contained = 0;
+ if (this.parsedKeywords.containsKey(keyword)) {
+ contained = this.parsedKeywords.get(keyword);
+ }
+ if (contained != 1) {
throw new DescriptorParseException("Keyword '" + keyword + "' is "
- + "contained " + this.parsedKeywords.get(keyword) + " times, "
- + "but must be contained exactly once.");
+ + "contained " + contained + " times, but must be contained "
+ + "exactly once.");
}
}
}
diff --git a/src/org/torproject/descriptor/impl/RelayNetworkStatusVoteImpl.java b/src/org/torproject/descriptor/impl/RelayNetworkStatusVoteImpl.java
index a7a5328..5089210 100644
--- a/src/org/torproject/descriptor/impl/RelayNetworkStatusVoteImpl.java
+++ b/src/org/torproject/descriptor/impl/RelayNetworkStatusVoteImpl.java
@@ -7,258 +7,341 @@ import java.io.IOException;
import java.io.StringReader;
import java.util.ArrayList;
import java.util.Arrays;
+import java.util.HashSet;
import java.util.List;
+import java.util.Set;
import java.util.SortedMap;
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.NetworkStatusEntry;
import org.torproject.descriptor.RelayNetworkStatusVote;
+/* TODO Find out if all keywords in the dir-source section are required.
+ * They are not all mentioned in dir-spec.txt. */
+
/* Contains a network status vote. */
-/* TODO This class is sharing a lot of parsing code with the consensus
- * class. Should there be an abstract super class for the two? */
-public class RelayNetworkStatusVoteImpl
+public class RelayNetworkStatusVoteImpl extends NetworkStatusImpl
implements RelayNetworkStatusVote {
protected static List<RelayNetworkStatusVote> parseVotes(
- byte[] voteBytes) {
+ byte[] votesBytes) {
List<RelayNetworkStatusVote> parsedVotes =
new ArrayList<RelayNetworkStatusVote>();
- String startToken = "network-status-version 3";
- String splitToken = "\n" + startToken;
- String ascii = new String(voteBytes);
- int length = voteBytes.length, start = ascii.indexOf(startToken);
- while (start < length) {
- int end = ascii.indexOf(splitToken, start);
- if (end < 0) {
- end = length;
- } else {
- end += 1;
+ List<byte[]> splitVotesBytes =
+ NetworkStatusImpl.splitRawDescriptorBytes(votesBytes,
+ "network-status-version 3");
+ try {
+ for (byte[] voteBytes : splitVotesBytes) {
+ RelayNetworkStatusVote parsedVote =
+ new RelayNetworkStatusVoteImpl(voteBytes);
+ parsedVotes.add(parsedVote);
}
- byte[] descBytes = new byte[end - start];
- System.arraycopy(voteBytes, start, descBytes, 0, end - start);
- RelayNetworkStatusVote parsedVote =
- new RelayNetworkStatusVoteImpl(descBytes);
- parsedVotes.add(parsedVote);
- start = end;
+ } catch (DescriptorParseException e) {
+ /* TODO Handle this error somehow. */
+ System.err.println("Failed to parse vote. Skipping.");
+ e.printStackTrace();
}
return parsedVotes;
}
- protected RelayNetworkStatusVoteImpl(byte[] voteBytes) {
- this.voteBytes = voteBytes;
- this.parseVoteBytes();
- this.checkConsistency();
- /* TODO Find a way to handle parse and consistency-check problems. */
+ protected RelayNetworkStatusVoteImpl(byte[] voteBytes)
+ throws DescriptorParseException {
+ super(voteBytes);
+ Set<String> exactlyOnceKeywords = new HashSet<String>(Arrays.asList((
+ "vote-status,consensus-methods,published,valid-after,fresh-until,"
+ + "valid-until,voting-delay,known-flags,dir-source,"
+ + "dir-key-certificate-version,fingerprint,dir-key-published,"
+ + "dir-key-expires,directory-footer").split(",")));
+ this.checkExactlyOnceKeywords(exactlyOnceKeywords);
+ Set<String> atMostOnceKeywords = new HashSet<String>(Arrays.asList((
+ "client-versions,server-versions,params,contact,legacy-key").
+ split(",")));
+ this.checkAtMostOnceKeywords(atMostOnceKeywords);
+ this.checkFirstKeyword("network-status-version");
}
- private void parseVoteBytes() {
- String line = null;
+ protected void parseHeader(byte[] headerBytes)
+ throws DescriptorParseException {
try {
BufferedReader br = new BufferedReader(new StringReader(
- new String(this.voteBytes)));
- SimpleDateFormat dateTimeFormat = new SimpleDateFormat(
- "yyyy-MM-dd HH:mm:ss");
- dateTimeFormat.setTimeZone(TimeZone.getTimeZone("UTC"));
- StringBuilder dirSourceEntryLines = null, statusEntryLines = null;
- boolean skipCrypto = false;
+ new String(headerBytes)));
+ String line;
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 vote")) {
- throw new RuntimeException("Line '" + line + "' indicates "
- + "that this string is not a vote. Aborting parsing.");
- }
- } else if (line.startsWith("consensus-methods ")) {
- for (String consensusMethodString : line.substring(
- "consensus-methods ".length()).split(" ")) {
- this.consensusMethods.add(Integer.parseInt(
- consensusMethodString));
- }
- } else if (line.startsWith("published ")) {
- this.publishedMillis = dateTimeFormat.parse(
- line.substring("published ".length())).getTime();
- } 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 =
- Arrays.asList(line.split(" ")[1].split(","));
- } else if (line.startsWith("server-versions ")) {
- this.recommendedServerVersions =
- 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];
- int paramValue = Integer.parseInt(param.split("=")[1]);
- this.consensusParams.put(paramName, paramValue);
- }
- }
- } else if (line.startsWith("dir-source ")) {
- String[] parts = line.split(" ");
- this.nickname = parts[1];
- this.identity = parts[2];
- this.address = parts[4];
- this.dirPort = Integer.parseInt(parts[5]);
- this.orPort = Integer.parseInt(parts[6]);
- /* TODO Add code for parsing legacy dir sources. */
- } else if (line.startsWith("contact ")) {
- this.contactLine = line.substring("contact ".length());
- } else if (line.startsWith("dir-key-certificate-version ")) {
- this.dirKeyCertificateVersion = Integer.parseInt(line.substring(
- "dir-key-certificate-version ".length()));
- } else if (line.startsWith("fingerprint ")) {
- /* Nothing new to learn here. We already know the fingerprint
- * from the dir-source line. */
- } else if (line.startsWith("dir-key-published ")) {
- this.dirKeyPublishedMillis = dateTimeFormat.parse(
- line.substring("dir-key-published ".length())).getTime();
- } else if (line.startsWith("dir-key-expires ")) {
- this.dirKeyExpiresMillis = dateTimeFormat.parse(
- line.substring("dir-key-expires ".length())).getTime();
- } else if (line.equals("dir-identity-key") ||
- line.equals("dir-signing-key") ||
- line.equals("dir-key-crosscert") ||
- line.equals("dir-key-certification")) {
- /* Ignore crypto parts for now. */
- } else if (line.startsWith("r ") ||
- line.equals("directory-footer")) {
- if (statusEntryLines != null) {
- 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 ")) {
- statusEntryLines = new StringBuilder();
- statusEntryLines.append(line + "\n");
- }
- } else if (line.startsWith("s ") || line.equals("s") ||
- line.startsWith("opt v ") || line.startsWith("w ") ||
- line.startsWith("p ") || line.startsWith("m ")) {
- statusEntryLines.append(line + "\n");
- } else if (line.startsWith("directory-signature ")) {
- String[] parts = line.split(" ");
- String identity = parts[1];
- String signingKeyDigest = parts[2];
- this.directorySignatures.put(identity, signingKeyDigest);
- } else if (line.startsWith("-----BEGIN")) {
- skipCrypto = true;
- } else if (line.startsWith("-----END")) {
- skipCrypto = false;
- } else if (!skipCrypto) {
- throw new RuntimeException("Unrecognized line '" + line + "'.");
+ String[] parts = line.split(" ");
+ String keyword = parts[0];
+ if (keyword.equals("network-status-version")) {
+ this.parseNetworkStatusVersionLine(line, parts);
+ } else if (keyword.equals("vote-status")) {
+ this.parseVoteStatusLine(line, parts);
+ } else if (keyword.equals("consensus-methods")) {
+ this.parseConsensusMethodsLine(line, parts);
+ } else if (keyword.equals("published")) {
+ this.parsePublishedLine(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 {
+ /* 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 correctly. */
- throw new RuntimeException("Parse error in line '" + line + "'.");
+ }
+ }
+
+ private void parseNetworkStatusVersionLine(String line, String[] parts)
+ throws DescriptorParseException {
+ if (!line.equals("network-status-version 3")) {
+ throw new DescriptorParseException("Illegal network status version "
+ + "number in line '" + line + "'.");
+ }
+ this.networkStatusVersion = 3;
+ }
+
+ private void parseVoteStatusLine(String line, String[] parts)
+ throws DescriptorParseException {
+ if (parts.length != 2 || !parts[1].equals("vote")) {
+ throw new DescriptorParseException("Line '" + line + "' indicates "
+ + "that this is not a vote.");
+ }
+ }
+
+ private void parseConsensusMethodsLine(String line, String[] parts)
+ throws DescriptorParseException {
+ if (parts.length < 2) {
+ throw new DescriptorParseException("Illegal line '" + line
+ + "' in vote.");
+ }
+ this.consensusMethods = new ArrayList<Integer>();
+ for (int i = 1; i < parts.length; i++) {
+ int consensusMethod = -1;
+ try {
+ consensusMethod = Integer.parseInt(parts[i]);
+ } catch (NumberFormatException e) {
+ /* We'll notice below that consensusMethod is still -1. */
+ }
+ if (consensusMethod < 1) {
+ throw new DescriptorParseException("Illegal consensus method "
+ + "number in line '" + line + "'.");
+ }
+ this.consensusMethods.add(Integer.parseInt(parts[i]));
+ }
+ }
+
+ private void parsePublishedLine(String line, String[] parts)
+ throws DescriptorParseException {
+ this.publishedMillis = ParseHelper.parseTimestampAtIndex(line, parts,
+ 1, 2);
+ }
+
+ private void parseValidAfterLine(String line, String[] parts)
+ throws DescriptorParseException {
+ this.validAfterMillis = ParseHelper.parseTimestampAtIndex(line, parts,
+ 1, 2);
+ }
+
+ private void parseFreshUntilLine(String line, String[] parts)
+ throws DescriptorParseException {
+ this.freshUntilMillis = ParseHelper.parseTimestampAtIndex(line, parts,
+ 1, 2);
+ }
+
+ private void parseValidUntilLine(String line, String[] parts)
+ throws DescriptorParseException {
+ this.validUntilMillis = ParseHelper.parseTimestampAtIndex(line, parts,
+ 1, 2);
+ }
+
+ private void parseVotingDelayLine(String line, String[] parts)
+ throws DescriptorParseException {
+ if (parts.length != 3) {
+ throw new DescriptorParseException("Wrong number of values in line "
+ + "'" + line + "'.");
+ }
+ try {
+ this.voteSeconds = Long.parseLong(parts[1]);
+ this.distSeconds = Long.parseLong(parts[2]);
} 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. */
+ throw new DescriptorParseException("Illegal values in line '" + line
+ + "'.");
}
}
- private byte[] voteBytes;
- public byte[] getRawDescriptorBytes() {
- return this.voteBytes;
+ private void parseClientVersionsLine(String line, String[] parts)
+ throws DescriptorParseException {
+ this.recommendedClientVersions = this.parseClientOrServerVersions(
+ line, parts);
}
- private int networkStatusVersion;
- public int getNetworkStatusVersion() {
- return this.networkStatusVersion;
+ private void parseServerVersionsLine(String line, String[] parts)
+ throws DescriptorParseException {
+ this.recommendedServerVersions = this.parseClientOrServerVersions(
+ line, parts);
}
- private List<Integer> consensusMethods = new ArrayList<Integer>();
- public List<Integer> getConsensusMethods() {
- return this.consensusMethods;
+ private List<String> parseClientOrServerVersions(String line,
+ String[] parts) throws DescriptorParseException {
+ List<String> result = new ArrayList<String>();
+ if (parts.length == 1) {
+ return result;
+ } else if (parts.length > 2) {
+ throw new DescriptorParseException("Illegal versions line '" + 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);
+ }
+ return result;
}
- private long publishedMillis;
- public long getPublishedMillis() {
- return this.publishedMillis;
+ private void parseKnownFlagsLine(String line, String[] parts)
+ throws DescriptorParseException {
+ if (parts.length < 2) {
+ throw new DescriptorParseException("No known flags in line '" + line
+ + "'.");
+ }
+ this.knownFlags = new TreeSet<String>();
+ for (int i = 1; i < parts.length; i++) {
+ this.knownFlags.add(parts[i]);
+ }
}
- private long validAfterMillis;
- public long getValidAfterMillis() {
- return this.validAfterMillis;
+ private void parseParamsLine(String line, String[] parts)
+ throws DescriptorParseException {
+ this.consensusParams = ParseHelper.parseKeyValuePairs(line, parts, 1);
}
- private long freshUntilMillis;
- public long getFreshUntilMillis() {
- return this.freshUntilMillis;
+ protected void parseDirSource(byte[] dirSourceBytes)
+ throws DescriptorParseException {
+ try {
+ BufferedReader br = new BufferedReader(new StringReader(
+ new String(dirSourceBytes)));
+ String line;
+ boolean skipCrypto = false;
+ while ((line = br.readLine()) != null) {
+ String[] parts = line.split(" ");
+ String keyword = parts[0];
+ if (keyword.equals("dir-source")) {
+ this.parseDirSourceLine(line, parts);
+ } else if (keyword.equals("contact")) {
+ this.parseContactLine(line, parts);
+ } else if (keyword.equals("dir-key-certificate-version")) {
+ this.parseDirKeyCertificateVersionLine(line, parts);
+ } else if (keyword.equals("fingerprint")) {
+ /* Nothing new to learn here. We already know the fingerprint
+ * from the dir-source line. */
+ } else if (keyword.equals("legacy-key")) {
+ this.parseLegacyKeyLine(line, parts);
+ } else if (keyword.equals("dir-key-published")) {
+ this.parseDirKeyPublished(line, parts);
+ } else if (keyword.equals("dir-key-expires")) {
+ this.parseDirKeyExpiresLine(line, parts);
+ } else if (keyword.equals("dir-identity-key") ||
+ keyword.equals("dir-signing-key") ||
+ keyword.equals("dir-key-crosscert") ||
+ keyword.equals("dir-key-certification")) {
+ } else if (line.startsWith("-----BEGIN")) {
+ skipCrypto = true;
+ } else if (line.equals("-----END")) {
+ skipCrypto = false;
+ } else if (!skipCrypto) {
+ /* 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);
+ }
}
- private long validUntilMillis;
- public long getValidUntilMillis() {
- return this.validUntilMillis;
+ private void parseDirSourceLine(String line, String[] parts)
+ throws DescriptorParseException {
+ this.nickname = ParseHelper.parseNickname(line, parts[1]);
+ this.identity = ParseHelper.parseTwentyByteHexString(line, parts[2]);
+ this.address = ParseHelper.parseIpv4Address(line, parts[4]);
+ this.dirPort = ParseHelper.parsePort(line, parts[5]);
+ this.orPort = ParseHelper.parsePort(line, parts[6]);
}
- private List<Long> votingDelay = new ArrayList<Long>();
- public List<Long> getVotingDelay() {
- return new ArrayList<Long>(this.votingDelay);
+ private void parseContactLine(String line, String[] parts)
+ throws DescriptorParseException {
+ if (line.length() > "contact ".length()) {
+ this.contactLine = line.substring("contact ".length());
+ } else {
+ this.contactLine = "";
+ }
}
- private List<String> recommendedClientVersions;
- public List<String> getRecommendedClientVersions() {
- return this.recommendedClientVersions == null ? null :
- new ArrayList<String>(this.recommendedClientVersions);
+ private void parseDirKeyCertificateVersionLine(String line,
+ String[] parts) throws DescriptorParseException {
+ if (parts.length != 2) {
+ throw new DescriptorParseException("Illegal line '" + line
+ + "' in vote.");
+ }
+ try {
+ this.dirKeyCertificateVersion = Integer.parseInt(parts[1]);
+ } catch (NumberFormatException e) {
+ throw new DescriptorParseException("Illegal dir key certificate "
+ + "version in line '" + line + "'.");
+ }
+ if (this.dirKeyCertificateVersion < 1) {
+ throw new DescriptorParseException("Illegal dir key certificate "
+ + "version in line '" + line + "'.");
+ }
}
- private List<String> recommendedServerVersions;
- public List<String> getRecommendedServerVersions() {
- return this.recommendedServerVersions == null ? null :
- new ArrayList<String>(this.recommendedServerVersions);
+ private void parseLegacyKeyLine(String line, String[] parts)
+ throws DescriptorParseException {
+ if (parts.length != 2) {
+ throw new DescriptorParseException("Illegal line '" + line + "'.");
+ }
+ this.legacyKey = ParseHelper.parseTwentyByteHexString(line, parts[2]);
}
- private SortedSet<String> knownFlags = new TreeSet<String>();
- public SortedSet<String> getKnownFlags() {
- return new TreeSet<String>(this.knownFlags);
+ private void parseDirKeyPublished(String line, String[] parts)
+ throws DescriptorParseException {
+ this.dirKeyPublishedMillis = ParseHelper.parseTimestampAtIndex(line,
+ parts, 1, 2);
}
- private SortedMap<String, Integer> consensusParams =
- new TreeMap<String, Integer>();
- public SortedMap<String, Integer> getConsensusParams() {
- return new TreeMap<String, Integer>(this.consensusParams);
+ private void parseDirKeyExpiresLine(String line, String[] parts)
+ throws DescriptorParseException {
+ this.dirKeyExpiresMillis = ParseHelper.parseTimestampAtIndex(line,
+ parts, 1, 2);
+ }
+
+ protected void parseFooter(byte[] footerBytes) {
+ /* There is nothing in the footer that we'd want to parse. */
}
private String nickname;
@@ -296,6 +379,11 @@ public class RelayNetworkStatusVoteImpl
return this.dirKeyCertificateVersion;
}
+ private String legacyKey;
+ public String getLegacyKey() {
+ return this.legacyKey;
+ }
+
private long dirKeyPublishedMillis;
public long getDirKeyPublishedMillis() {
return this.dirKeyPublishedMillis;
@@ -311,54 +399,67 @@ public class RelayNetworkStatusVoteImpl
return this.signingKeyDigest;
}
- private SortedMap<String, NetworkStatusEntry> statusEntries =
- new TreeMap<String, NetworkStatusEntry>();
- public SortedMap<String, NetworkStatusEntry> getStatusEntries() {
- return new TreeMap<String, NetworkStatusEntry>(this.statusEntries);
+ private int networkStatusVersion;
+ public int getNetworkStatusVersion() {
+ return this.networkStatusVersion;
}
- public boolean containsStatusEntry(String fingerprint) {
- return this.statusEntries.containsKey(fingerprint);
+
+ private List<Integer> consensusMethods;
+ public List<Integer> getConsensusMethods() {
+ return new ArrayList<Integer>(this.consensusMethods);
}
- public NetworkStatusEntry getStatusEntry(String fingerprint) {
- return this.statusEntries.get(fingerprint);
+
+ private long publishedMillis;
+ public long getPublishedMillis() {
+ return this.publishedMillis;
}
+ private long validAfterMillis;
+ public long getValidAfterMillis() {
+ return this.validAfterMillis;
+ }
- private SortedMap<String, String> directorySignatures =
- new TreeMap<String, String>();
- public SortedMap<String, String> getDirectorySignatures() {
- return new TreeMap<String, String>(this.directorySignatures);
+ private long freshUntilMillis;
+ public long getFreshUntilMillis() {
+ return this.freshUntilMillis;
}
- private void checkConsistency() {
- if (this.networkStatusVersion == 0) {
- throw new RuntimeException("Consensus doesn't contain a "
- + "'network-status-version' line.");
- }
- if (this.validAfterMillis == 0L) {
- throw new RuntimeException("Consensus doesn't contain a "
- + "'valid-after' line.");
- }
- if (this.freshUntilMillis == 0L) {
- throw new RuntimeException("Consensus doesn't contain a "
- + "'fresh-until' line.");
- }
- if (this.validUntilMillis == 0L) {
- throw new RuntimeException("Consensus doesn't contain a "
- + "'valid-until' line.");
- }
- if (this.votingDelay.isEmpty()) {
- throw new RuntimeException("Consensus doesn't contain a "
- + "'voting-delay' line.");
- }
- if (this.knownFlags.isEmpty()) {
- throw new RuntimeException("Consensus doesn't contain a "
- + "'known-flags' line.");
- }
- if (this.statusEntries.isEmpty()) {
- throw new RuntimeException("Consensus doesn't contain any 'r' "
- + "lines.");
- }
+ private long validUntilMillis;
+ public long getValidUntilMillis() {
+ return this.validUntilMillis;
+ }
+
+ private long voteSeconds;
+ public long getVoteSeconds() {
+ return this.voteSeconds;
+ }
+
+ private long distSeconds;
+ public long getDistSeconds() {
+ return this.distSeconds;
+ }
+
+ private List<String> recommendedClientVersions;
+ public List<String> getRecommendedClientVersions() {
+ return this.recommendedClientVersions == null ? null :
+ new ArrayList<String>(this.recommendedClientVersions);
+ }
+
+ private List<String> recommendedServerVersions;
+ public List<String> getRecommendedServerVersions() {
+ return this.recommendedServerVersions == null ? null :
+ new ArrayList<String>(this.recommendedServerVersions);
+ }
+
+ private SortedSet<String> knownFlags;
+ public SortedSet<String> getKnownFlags() {
+ return new TreeSet<String>(this.knownFlags);
+ }
+
+ private SortedMap<String, Integer> consensusParams;
+ public SortedMap<String, Integer> getConsensusParams() {
+ return this.consensusParams == null ? null:
+ new TreeMap<String, Integer>(this.consensusParams);
}
}
diff --git a/test/org/torproject/descriptor/impl/RelayNetworkStatusVoteImplTest.java b/test/org/torproject/descriptor/impl/RelayNetworkStatusVoteImplTest.java
new file mode 100644
index 0000000..8b62480
--- /dev/null
+++ b/test/org/torproject/descriptor/impl/RelayNetworkStatusVoteImplTest.java
@@ -0,0 +1,574 @@
+/* Copyright 2011 The Tor Project
+ * See LICENSE for licensing information */
+package org.torproject.descriptor.impl;
+
+import org.torproject.descriptor.RelayNetworkStatusVote;
+import org.torproject.descriptor.impl.RelayNetworkStatusVoteImpl;
+
+import java.util.*;
+
+import org.junit.*;
+import org.junit.rules.*;
+import static org.junit.Assert.*;
+
+/* TODO Add tests (and possibly a DirSourceLineBuilder) to test the
+ * following methods:
+ * - String getNickname();
+ * - String getIdentity();
+ * - String getAddress();
+ * - int getDirport();
+ * - int getOrport();
+ * - String getContactLine();
+ * - int getDirKeyCertificateVersion();
+ * - String getLegacyKey();
+ * - long getDirKeyPublishedMillis();
+ * - long getDirKeyExpiresMillis();
+ * - String getSigningKeyDigest();
+ */
+
+/* Test parsing of network status votes. Some of the vote-parsing code is
+ * already tested in the consensus-parsing tests. The tests in this class
+ * focus on the differences between votes and consensuses that are mostly
+ * in the directory header. */
+public class RelayNetworkStatusVoteImplTest {
+
+ /* Helper class to build a vote based on default data and modifications
+ * requested by test methods. */
+ private static class VoteBuilder {
+ private String networkStatusVersionLine = "network-status-version 3";
+ private static RelayNetworkStatusVote
+ createWithNetworkStatusVersionLine(String line)
+ throws DescriptorParseException {
+ VoteBuilder vb = new VoteBuilder();
+ vb.networkStatusVersionLine = line;
+ return new RelayNetworkStatusVoteImpl(vb.buildVote());
+ }
+ private String voteStatusLine = "vote-status vote";
+ private static RelayNetworkStatusVote
+ createWithVoteStatusLine(String line)
+ throws DescriptorParseException {
+ VoteBuilder vb = new VoteBuilder();
+ vb.voteStatusLine = line;
+ return new RelayNetworkStatusVoteImpl(vb.buildVote());
+ }
+ private String consensusMethodsLine =
+ "consensus-methods 1 2 3 4 5 6 7 8 9 10 11";
+ private static RelayNetworkStatusVote
+ createWithConsensusMethodsLine(String line)
+ throws DescriptorParseException {
+ VoteBuilder vb = new VoteBuilder();
+ vb.consensusMethodsLine = line;
+ return new RelayNetworkStatusVoteImpl(vb.buildVote());
+ }
+ private String publishedLine = "published 2011-11-30 08:50:01";
+ private static RelayNetworkStatusVote
+ createWithPublishedLine(String line)
+ throws DescriptorParseException {
+ VoteBuilder vb = new VoteBuilder();
+ vb.publishedLine = line;
+ return new RelayNetworkStatusVoteImpl(vb.buildVote());
+ }
+ private String validAfterLine = "valid-after 2011-11-30 09:00:00";
+ private static RelayNetworkStatusVote
+ createWithValidAfterLine(String line)
+ throws DescriptorParseException {
+ VoteBuilder vb = new VoteBuilder();
+ vb.validAfterLine = line;
+ return new RelayNetworkStatusVoteImpl(vb.buildVote());
+ }
+ private String freshUntilLine = "fresh-until 2011-11-30 10:00:00";
+ private static RelayNetworkStatusVote
+ createWithFreshUntilLine(String line)
+ throws DescriptorParseException {
+ VoteBuilder vb = new VoteBuilder();
+ vb.freshUntilLine = line;
+ return new RelayNetworkStatusVoteImpl(vb.buildVote());
+ }
+ private String validUntilLine = "valid-until 2011-11-30 12:00:00";
+ private static RelayNetworkStatusVote
+ createWithValidUntilLine(String line)
+ throws DescriptorParseException {
+ VoteBuilder vb = new VoteBuilder();
+ vb.validUntilLine = line;
+ return new RelayNetworkStatusVoteImpl(vb.buildVote());
+ }
+ private String votingDelayLine = "voting-delay 300 300";
+ private static RelayNetworkStatusVote
+ createWithVotingDelayLine(String line)
+ throws DescriptorParseException {
+ VoteBuilder vb = new VoteBuilder();
+ vb.votingDelayLine = line;
+ return new RelayNetworkStatusVoteImpl(vb.buildVote());
+ }
+ 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 RelayNetworkStatusVote
+ createWithClientVersionsLine(String line)
+ throws DescriptorParseException {
+ VoteBuilder vb = new VoteBuilder();
+ vb.clientVersionsLine = line;
+ return new RelayNetworkStatusVoteImpl(vb.buildVote());
+ }
+ 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 RelayNetworkStatusVote
+ createWithServerVersionsLine(String line)
+ throws DescriptorParseException {
+ VoteBuilder vb = new VoteBuilder();
+ vb.serverVersionsLine = line;
+ return new RelayNetworkStatusVoteImpl(vb.buildVote());
+ }
+ private String knownFlagsLine = "known-flags Authority BadExit Exit "
+ + "Fast Guard HSDir Named Running Stable Unnamed V2Dir Valid";
+ private static RelayNetworkStatusVote
+ createWithKnownFlagsLine(String line)
+ throws DescriptorParseException {
+ VoteBuilder vb = new VoteBuilder();
+ vb.knownFlagsLine = line;
+ return new RelayNetworkStatusVoteImpl(vb.buildVote());
+ }
+ 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 RelayNetworkStatusVote
+ createWithParamsLine(String line)
+ throws DescriptorParseException {
+ VoteBuilder vb = new VoteBuilder();
+ vb.paramsLine = line;
+ return new RelayNetworkStatusVoteImpl(vb.buildVote());
+ }
+ private List<String> dirSources = new ArrayList<String>();
+ private List<String> statusEntries = new ArrayList<String>();
+ private String directoryFooterLine = "directory-footer";
+ private static RelayNetworkStatusVote
+ createWithDirectoryFooterLine(String line)
+ throws DescriptorParseException {
+ VoteBuilder vb = new VoteBuilder();
+ vb.directoryFooterLine = line;
+ return new RelayNetworkStatusVoteImpl(vb.buildVote());
+ }
+ private List<String> directorySignatures = new ArrayList<String>();
+ private VoteBuilder() {
+ this.dirSources.add("dir-source urras "
+ + "80550987E1D626E3EBA5E5E75A458DE0626D088C 208.83.223.34 "
+ + "208.83.223.34 443 80\n"
+ + "contact 4096R/E012B42D Jacob Appelbaum "
+ + "<jacob@xxxxxxxxxxxxx>\n"
+ + "dir-key-certificate-version 3\n"
+ + "fingerprint 80550987E1D626E3EBA5E5E75A458DE0626D088C\n"
+ + "dir-key-published 2011-04-27 05:34:37\n"
+ + "dir-key-expires 2012-04-27 05:34:37\n"
+ + "dir-identity-key\n"
+ + "-----BEGIN RSA PUBLIC KEY-----\n"
+ + "MIIBigKCAYEAtKpuLgVK25sfScjsxfVU1ljofrDygt9GP7bNJl/rghX42KUT"
+ + "975W\nrGp/fbhF7p+FcKCzNOhJFINQbRf/5E3lN8mzoamIU43QqQ9RRVf946"
+ + "88UsazVsAN\nNVT0v9J0cr387WePjenRuIE1MmiP0nmw/XdvbPTayqax7VYl"
+ + "cUMXGHl8DnWix1EN\nRwmeig+JBte0JS12oo2HG9zcSfjLJVjY6ZmvRrVycX"
+ + "iRxGc/JgNlSrV4cxUNykaB\nJ6pO6J499OZfQu7m1vAPTENrVJ4yEfRGRwFI"
+ + "Y+d/s8BkKcaiWtXAfTe31uBI6GEH\nmS3HNu1JVSuoaUiQIvVYDLMfBvMcNy"
+ + "Ax97UT1l6E0Tn6a7pgChrquGwXai1xGzk8\n58aXwdSFoFBSTCkyemopq5H2"
+ + "0p/nkPAO0pHL1kTvcaKz9CEj4XcKm+kOmzejYmIa\nkbWNcRpXPiUZ+xmwGt"
+ + "sq30xrzqiONmERkxqlmf7bVQPFvh3Kz6hGcmTBhTbHSe9h\nzDgmdaTNn3EH"
+ + "AgMBAAE=\n"
+ + "-----END RSA PUBLIC KEY-----\n"
+ + "dir-signing-key\n"
+ + "-----BEGIN RSA PUBLIC KEY-----\n"
+ + "MIGJAoGBAN05qyHFQlTqykMP8yLuD4G2UuYulD4Xs8iSX5uqF+WGsUA1E4zZ"
+ + "h48h\nDFj8+drFiCu3EqhMEmVG4ACtJK2uz6D1XohUsbPWTR6LSnWJ8q6/zf"
+ + "TSLumBGsN7\nPUXyMNjwRKL6UvrcbYk1d2mRBLO7SAP/sFW5fHhIBVeLIWrz"
+ + "Q19rAgMBAAE=\n"
+ + "-----END RSA PUBLIC KEY-----\n"
+ + "dir-key-crosscert\n"
+ + "-----BEGIN ID SIGNATURE-----\n"
+ + "rPBFn6IJ6TvAHj4pSwlg+RTn1fP89JGSVa08wuyJr5dAvZsdakQXvRjamT9o"
+ + "JUaZ\nnY5Rl/tRlGuSQ0BglTPPKoXdKERK0FUr9f0EKrQy7NDUgE2j9losiR"
+ + "uyKzhA3neZ\nK4yF8bhqAwM51u7fzAhIjNeRif9c04rhFJJCseco84w=\n"
+ + "-----END ID SIGNATURE-----\n"
+ + "dir-key-certification\n"
+ + "-----BEGIN SIGNATURE-----\n"
+ + "hPSh6FuohNF5ccjiMbkvr8cZJwGFuL11cNtwN9k0X3pUdFZVATIEkqBe7z+r"
+ + "E2PX\nPw+BGyC6wYAieoTVIhLpwKqd7DXLYjuhPZ28+7MQaDL01AqYeRp5PT"
+ + "01PxrFY0Um\nlVf95uqUitgvDT76Ne4ExWk6UvGlYB9OBgBySZz8VWe9znoM"
+ + "qb0uHn/p8IzqTApT\nAxRWXBHClntMeRqtGxaj8DcdJFn8yMxQiZG7MfDg2s"
+ + "q2ySPJyGlN+neoVDVhZiDI\n9LTNmw60gWlUp2erFeam8Mo1ZBC4DPNjQEm6"
+ + "QeHZFZMkhDuO6SwS/FL712A42+Co\nYtMaVot/p5FG2ZSBXbgl2XP5/z8ELn"
+ + "pmXqMbPAoWRo3BPNSJkIQQNog8Q5ZrK+av\nZDw5eGPltGKsXOkvuzIMM8nB"
+ + "eAnDPDgYvzrIFObEGbvY/P8mzVAZxp3Yz+sRtNel\nC1SWz/Fx+Saex5oI7D"
+ + "J3xtSD4XqKb/wYwZFT8IxDYq1t2tFXdHxd4QPRVcvc0zYC\n"
+ + "-----END SIGNATURE-----");
+ this.statusEntries.add("r right2privassy3 "
+ + "ADQ6gCT3DiFHKPDFr3rODBUI8HM lJY5Vf7kXec+VdkGW2flEsfkFC8 "
+ + "2011-11-12 00:03:40 50.63.8.215 9023 0\n"
+ + "s Exit Fast Guard Running Stable Valid\n"
+ + "opt v Tor 0.2.1.29 (r8e9b25e6c7a2e70c)\n"
+ + "w Bandwidth=297 Measured=73\n"
+ + "p accept 80,1194,1220,1293,1500,1533,1677,1723,1863,"
+ + "2082-2083,2086-2087,2095-2096,2102-2104,3128,3389,3690,4321,"
+ + "4643,5050,5190,5222-5223,5228,5900,6660-6669,6679,6697,8000,"
+ + "8008,8074,8080,8087-8088,8443,8888,9418,9999-10000,19294,"
+ + "19638\n"
+ + "m 8,9,10,11 sha256=9ciEx9t0McXk9A06I7qwN7pxuNOdpCP64RV/6cx2Zkc");
+ this.directorySignatures.add("directory-signature "
+ + "80550987E1D626E3EBA5E5E75A458DE0626D088C "
+ + "EEB9299D295C1C815E289FBF2F2BBEA5F52FDD19\n"
+ + "-----BEGIN SIGNATURE-----\n"
+ + "iHEU3Iidya5RIrjyYgv8tlU0R+rF56/3/MmaaZi0a67e7ZkISfQ4dghScHxn"
+ + "F3Yh\nqXVaaoP07r6Ta+s0g1Zijm3lms50Nk/4tV2p8Y63c3F4Q3DAnK40Oi"
+ + "kfOIwEj+Ny\n+zBRQssP3hPhTPOj/A7o3mZZwtL6x1sxpeu/nME1l5E=\n"
+ + "-----END SIGNATURE-----");
+ }
+ private byte[] buildVote() {
+ StringBuilder sb = new StringBuilder();
+ this.appendHeader(sb);
+ this.appendBody(sb);
+ this.appendFooter(sb);
+ return sb.toString().getBytes();
+ }
+ private void appendHeader(StringBuilder sb) {
+ if (this.networkStatusVersionLine != null) {
+ sb.append(this.networkStatusVersionLine + "\n");
+ }
+ if (this.voteStatusLine != null) {
+ sb.append(this.voteStatusLine + "\n");
+ }
+ if (this.consensusMethodsLine != null) {
+ sb.append(this.consensusMethodsLine + "\n");
+ }
+ if (this.publishedLine != null) {
+ sb.append(this.publishedLine + "\n");
+ }
+ if (this.validAfterLine != null) {
+ sb.append(this.validAfterLine + "\n");
+ }
+ if (this.freshUntilLine != null) {
+ sb.append(this.freshUntilLine + "\n");
+ }
+ if (this.validUntilLine != null) {
+ sb.append(this.validUntilLine + "\n");
+ }
+ if (this.votingDelayLine != null) {
+ sb.append(this.votingDelayLine + "\n");
+ }
+ if (this.clientVersionsLine != null) {
+ sb.append(this.clientVersionsLine + "\n");
+ }
+ if (this.serverVersionsLine != null) {
+ sb.append(this.serverVersionsLine + "\n");
+ }
+ if (this.knownFlagsLine != null) {
+ sb.append(this.knownFlagsLine + "\n");
+ }
+ if (this.paramsLine != null) {
+ sb.append(this.paramsLine + "\n");
+ }
+ for (String dirSource : this.dirSources) {
+ sb.append(dirSource + "\n");
+ }
+ }
+ private void appendBody(StringBuilder sb) {
+ for (String statusEntry : this.statusEntries) {
+ sb.append(statusEntry + "\n");
+ }
+ }
+ private void appendFooter(StringBuilder sb) {
+ if (this.directoryFooterLine != null) {
+ sb.append(this.directoryFooterLine + "\n");
+ }
+ for (String directorySignature : this.directorySignatures) {
+ sb.append(directorySignature + "\n");
+ }
+ }
+ }
+
+ @Test()
+ public void testSampleVote() throws DescriptorParseException {
+ VoteBuilder vb = new VoteBuilder();
+ RelayNetworkStatusVote vote =
+ new RelayNetworkStatusVoteImpl(vb.buildVote());
+ assertEquals(3, vote.getNetworkStatusVersion());
+ List<Integer> consensusMethods = Arrays.asList(
+ new Integer[] {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11});
+ assertEquals(vote.getConsensusMethods(), consensusMethods);
+ assertEquals(1322643001000L, vote.getPublishedMillis());
+ assertEquals(1322643600000L, vote.getValidAfterMillis());
+ assertEquals(1322647200000L, vote.getFreshUntilMillis());
+ assertEquals(1322654400000L, vote.getValidUntilMillis());
+ assertEquals(300L, vote.getVoteSeconds());
+ assertEquals(300L, vote.getDistSeconds());
+ assertTrue(vote.getKnownFlags().contains("Running"));
+ assertEquals(30000, (int) vote.getConsensusParams().get(
+ "CircuitPriorityHalflifeMsec"));
+ assertEquals("Tor 0.2.1.29 (r8e9b25e6c7a2e70c)",
+ vote.getStatusEntry("00343A8024F70E214728F0C5AF7ACE0C1508F073").
+ getVersion());
+ }
+
+ @Test(expected = DescriptorParseException.class)
+ public void testNetworkStatusVersionNoLine()
+ throws DescriptorParseException {
+ VoteBuilder.createWithNetworkStatusVersionLine(null);
+ }
+
+ @Test(expected = DescriptorParseException.class)
+ public void testNetworkStatusVersionNewLine()
+ throws DescriptorParseException {
+ VoteBuilder.createWithNetworkStatusVersionLine(
+ "network-status-version 3\n");
+ }
+
+ @Test(expected = DescriptorParseException.class)
+ public void testNetworkStatusVersionNewLineSpace()
+ throws DescriptorParseException {
+ VoteBuilder.createWithNetworkStatusVersionLine(
+ "network-status-version 3\n ");
+ }
+
+ @Test(expected = DescriptorParseException.class)
+ public void testNetworkStatusVersionPrefixLineAtChar()
+ throws DescriptorParseException {
+ VoteBuilder.createWithNetworkStatusVersionLine(
+ "@vote\nnetwork-status-version 3");
+ }
+
+ @Test(expected = DescriptorParseException.class)
+ public void testNetworkStatusVersionPrefixLine()
+ throws DescriptorParseException {
+ VoteBuilder.createWithNetworkStatusVersionLine(
+ "directory-footer\nnetwork-status-version 3");
+ }
+
+ @Test(expected = DescriptorParseException.class)
+ public void testNetworkStatusVersionPrefixLinePoundChar()
+ throws DescriptorParseException {
+ VoteBuilder.createWithNetworkStatusVersionLine(
+ "#vote\nnetwork-status-version 3");
+ }
+
+ @Test(expected = DescriptorParseException.class)
+ public void testNetworkStatusVersionNoSpace()
+ throws DescriptorParseException {
+ VoteBuilder.createWithNetworkStatusVersionLine(
+ "network-status-version");
+ }
+
+ @Test(expected = DescriptorParseException.class)
+ public void testNetworkStatusVersionOneSpace()
+ throws DescriptorParseException {
+ VoteBuilder.createWithNetworkStatusVersionLine(
+ "network-status-version ");
+ }
+
+ @Test(expected = DescriptorParseException.class)
+ public void testNetworkStatusVersion42()
+ throws DescriptorParseException {
+ VoteBuilder.createWithNetworkStatusVersionLine(
+ "network-status-version 42");
+ }
+
+ @Test(expected = DescriptorParseException.class)
+ public void testNetworkStatusVersionFourtyTwo()
+ throws DescriptorParseException {
+ VoteBuilder.createWithNetworkStatusVersionLine(
+ "network-status-version FourtyTwo");
+ }
+
+ @Test(expected = DescriptorParseException.class)
+ public void testVoteStatusNoLine() throws DescriptorParseException {
+ VoteBuilder.createWithVoteStatusLine(null);
+ }
+
+ @Test(expected = DescriptorParseException.class)
+ public void testNetworkStatusVersionSpaceBefore()
+ throws DescriptorParseException {
+ VoteBuilder.createWithNetworkStatusVersionLine(
+ " network-status-version 3");
+ }
+
+ @Test(expected = DescriptorParseException.class)
+ public void testVoteStatusSpaceBefore() throws DescriptorParseException {
+ VoteBuilder.createWithVoteStatusLine(" vote-status vote");
+ }
+
+ @Test(expected = DescriptorParseException.class)
+ public void testVoteStatusNoSpace() throws DescriptorParseException {
+ VoteBuilder.createWithVoteStatusLine("vote-status");
+ }
+
+ @Test(expected = DescriptorParseException.class)
+ public void testVoteStatusOneSpace() throws DescriptorParseException {
+ VoteBuilder.createWithVoteStatusLine("vote-status ");
+ }
+
+ @Test()
+ public void testVoteStatusVoteOneSpace()
+ throws DescriptorParseException {
+ VoteBuilder.createWithVoteStatusLine("vote-status vote ");
+ }
+
+ @Test(expected = DescriptorParseException.class)
+ public void testVoteStatusConsensus() throws DescriptorParseException {
+ VoteBuilder.createWithVoteStatusLine("vote-status consensus");
+ }
+
+ @Test(expected = DescriptorParseException.class)
+ public void testVoteStatusTheMagicVoteStatus()
+ throws DescriptorParseException {
+ VoteBuilder.createWithVoteStatusLine(
+ "vote-status TheMagicVoteStatus");
+ }
+
+ @Test(expected = DescriptorParseException.class)
+ public void testConsensusMethodNoLine()
+ throws DescriptorParseException {
+ VoteBuilder.createWithConsensusMethodsLine(null);
+ }
+
+ @Test(expected = DescriptorParseException.class)
+ public void testConsensusMethodNoSpace()
+ throws DescriptorParseException {
+ VoteBuilder.createWithConsensusMethodsLine("consensus-methods");
+ }
+
+ @Test(expected = DescriptorParseException.class)
+ public void testConsensusMethodOneSpace()
+ throws DescriptorParseException {
+ VoteBuilder.createWithConsensusMethodsLine("consensus-methods ");
+ }
+
+ @Test(expected = DescriptorParseException.class)
+ public void testConsensusMethodEleven()
+ throws DescriptorParseException {
+ VoteBuilder.createWithConsensusMethodsLine(
+ "consensus-methods eleven");
+ }
+
+ @Test(expected = DescriptorParseException.class)
+ public void testConsensusMethodMinusOne()
+ throws DescriptorParseException {
+ VoteBuilder.createWithConsensusMethodsLine("consensus-methods -1");
+ }
+
+ @Test(expected = DescriptorParseException.class)
+ public void testConsensusMethodNinePeriod()
+ throws DescriptorParseException {
+ VoteBuilder.createWithConsensusMethodsLine("consensus-methods "
+ + "999999999999999999999999999999999999999999999999999999999999");
+ }
+
+ @Test(expected = DescriptorParseException.class)
+ public void testConsensusMethodTwoLines()
+ throws DescriptorParseException {
+ VoteBuilder.createWithConsensusMethodsLine(
+ "consensus-method 1\nconsensus-method 1");
+ }
+
+ @Test(expected = DescriptorParseException.class)
+ public void testPublishedNoLine() throws DescriptorParseException {
+ VoteBuilder.createWithPublishedLine(null);
+ }
+
+ @Test(expected = DescriptorParseException.class)
+ public void testValidAfterNoLine() throws DescriptorParseException {
+ VoteBuilder.createWithValidAfterLine(null);
+ }
+
+ @Test(expected = DescriptorParseException.class)
+ public void testValidAfterNoSpace() throws DescriptorParseException {
+ VoteBuilder.createWithValidAfterLine("valid-after");
+ }
+
+ @Test(expected = DescriptorParseException.class)
+ public void testValidAfterOneSpace() throws DescriptorParseException {
+ VoteBuilder.createWithValidAfterLine("valid-after ");
+ }
+
+ @Test(expected = DescriptorParseException.class)
+ public void testValidAfterLongAgo() throws DescriptorParseException {
+ VoteBuilder.createWithValidAfterLine("valid-after long ago");
+ }
+
+ @Test(expected = DescriptorParseException.class)
+ public void testValidAfterFeb30() throws DescriptorParseException {
+ VoteBuilder.createWithValidAfterLine(
+ "valid-after 2011-02-30 09:00:00");
+ }
+
+ @Test(expected = DescriptorParseException.class)
+ public void testFreshUntilNoLine() throws DescriptorParseException {
+ VoteBuilder.createWithFreshUntilLine(null);
+ }
+
+ @Test(expected = DescriptorParseException.class)
+ public void testFreshUntilAroundTen() throws DescriptorParseException {
+ VoteBuilder.createWithFreshUntilLine(
+ "fresh-until 2011-11-30 around ten");
+ }
+
+ @Test(expected = DescriptorParseException.class)
+ public void testValidUntilTomorrowMorning()
+ throws DescriptorParseException {
+ VoteBuilder.createWithValidUntilLine(
+ "valid-until tomorrow morning");
+ }
+
+ @Test(expected = DescriptorParseException.class)
+ public void testVotingDelayNoLine() throws DescriptorParseException {
+ VoteBuilder.createWithVotingDelayLine(null);
+ }
+
+ @Test(expected = DescriptorParseException.class)
+ public void testVotingDelayNoSpace() throws DescriptorParseException {
+ VoteBuilder.createWithVotingDelayLine("voting-delay");
+ }
+
+ @Test(expected = DescriptorParseException.class)
+ public void testVotingDelayOneSpace() throws DescriptorParseException {
+ VoteBuilder.createWithVotingDelayLine("voting-delay ");
+ }
+
+ @Test(expected = DescriptorParseException.class)
+ public void testVotingDelayTriple() throws DescriptorParseException {
+ VoteBuilder.createWithVotingDelayLine(
+ "voting-delay 300 300 300");
+ }
+
+ @Test(expected = DescriptorParseException.class)
+ public void testVotingDelaySingle() throws DescriptorParseException {
+ VoteBuilder.createWithVotingDelayLine("voting-delay 300");
+ }
+
+ @Test(expected = DescriptorParseException.class)
+ public void testVotingDelayOneTwo() throws DescriptorParseException {
+ VoteBuilder.createWithVotingDelayLine("voting-delay one two");
+ }
+
+ @Test(expected = DescriptorParseException.class)
+ public void testClientVersionsComma() throws DescriptorParseException {
+ VoteBuilder.createWithClientVersionsLine("client-versions ,");
+ }
+
+ @Test(expected = DescriptorParseException.class)
+ public void testClientVersionsCommaVersion()
+ throws DescriptorParseException {
+ VoteBuilder.createWithClientVersionsLine(
+ "client-versions ,0.2.2.34");
+ }
+
+ @Test(expected = DescriptorParseException.class)
+ public void testKnownFlagsNoLine() throws DescriptorParseException {
+ VoteBuilder.createWithKnownFlagsLine(null);
+ }
+
+ @Test(expected = DescriptorParseException.class)
+ public void testKnownFlagsNoSpace() throws DescriptorParseException {
+ VoteBuilder.createWithKnownFlagsLine("known-flags");
+ }
+
+ @Test(expected = DescriptorParseException.class)
+ public void testKnownFlagsOneSpace() throws DescriptorParseException {
+ VoteBuilder.createWithKnownFlagsLine("known-flags ");
+ }
+}
+
_______________________________________________
tor-commits mailing list
tor-commits@xxxxxxxxxxxxxxxxxxxx
https://lists.torproject.org/cgi-bin/mailman/listinfo/tor-commits