[tor-commits] [onionoo/master] Extend order parameter to first_seen.
karsten at torproject.org
karsten at torproject.org
Wed Jan 11 13:42:25 UTC 2017
commit 817b93caca99a2cdf92ac6877009a061b67a36e0
Author: Karsten Loesing <karsten.loesing at gmx.net>
Date: Wed Jan 11 14:40:40 2017 +0100
Extend order parameter to first_seen.
Implements #21095.
---
CHANGELOG.md | 3 +-
build.xml | 2 +-
.../onionoo/docs/DetailsDocumentFields.java | 13 +++
.../org/torproject/onionoo/server/NodeIndex.java | 12 ---
.../org/torproject/onionoo/server/NodeIndexer.java | 15 ---
.../onionoo/server/OrderParameterValues.java | 24 +++++
.../torproject/onionoo/server/RequestHandler.java | 43 ++++-----
.../torproject/onionoo/server/ResourceServlet.java | 40 ++++++--
.../torproject/onionoo/server/ResponseBuilder.java | 7 +-
.../onionoo/server/SummaryDocumentComparator.java | 51 ++++++++++
src/main/resources/web/protocol.html | 7 +-
.../onionoo/server/ResourceServletTest.java | 59 ++++++++++--
.../server/SummaryDocumentComparatorTest.java | 105 +++++++++++++++++++++
13 files changed, 307 insertions(+), 74 deletions(-)
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 6d01ec0..4ed4e98 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,4 +1,4 @@
-# Changes in version x.x.x - 2017-xx-xx
+# Changes in version 3.2-1.x.x - 2017-xx-xx
* Major changes
- Fix a bug where we'd believe that we have first seen a bridge on
@@ -13,6 +13,7 @@
- Accept the same characters in qualified search terms as in their
parameter equivalents.
- Exclude bandwidth history values from the future.
+ - Extend order parameter to "first_seen".
* Minor changes
- Include XZ binaries in release binaries.
diff --git a/build.xml b/build.xml
index 3c2ad5c..5bfea72 100644
--- a/build.xml
+++ b/build.xml
@@ -8,7 +8,7 @@
<property name="javadoc-title" value="Onionoo API Documentation"/>
<property name="implementation-title" value="Onionoo" />
- <property name="onionoo.protocol.version" value="3.1"/>
+ <property name="onionoo.protocol.version" value="3.2"/>
<property name="release.version"
value="${onionoo.protocol.version}-1.0.0-dev"/>
<property name="descriptorversion" value="1.5.0"/>
diff --git a/src/main/java/org/torproject/onionoo/docs/DetailsDocumentFields.java b/src/main/java/org/torproject/onionoo/docs/DetailsDocumentFields.java
new file mode 100644
index 0000000..df46149
--- /dev/null
+++ b/src/main/java/org/torproject/onionoo/docs/DetailsDocumentFields.java
@@ -0,0 +1,13 @@
+/* Copyright 2017 The Tor Project
+ * See LICENSE for licensing information */
+
+package org.torproject.onionoo.docs;
+
+/** Provides constants for details document field names. */
+public interface DetailsDocumentFields {
+
+ public static final String FIRST_SEEN = "first_seen";
+
+ public static final String CONSENSUS_WEIGHT = "consensus_weight";
+}
+
diff --git a/src/main/java/org/torproject/onionoo/server/NodeIndex.java b/src/main/java/org/torproject/onionoo/server/NodeIndex.java
index 9f9cf74..439d302 100644
--- a/src/main/java/org/torproject/onionoo/server/NodeIndex.java
+++ b/src/main/java/org/torproject/onionoo/server/NodeIndex.java
@@ -6,7 +6,6 @@ package org.torproject.onionoo.server;
import org.torproject.onionoo.docs.SummaryDocument;
import java.text.SimpleDateFormat;
-import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.SortedMap;
@@ -42,17 +41,6 @@ class NodeIndex {
return bridgesPublishedString;
}
- private List<String> relaysByConsensusWeight;
-
- public void setRelaysByConsensusWeight(
- List<String> relaysByConsensusWeight) {
- this.relaysByConsensusWeight = relaysByConsensusWeight;
- }
-
- public List<String> getRelaysByConsensusWeight() {
- return relaysByConsensusWeight;
- }
-
private Map<String, SummaryDocument> relayFingerprintSummaryLines;
public void setRelayFingerprintSummaryLines(
diff --git a/src/main/java/org/torproject/onionoo/server/NodeIndexer.java b/src/main/java/org/torproject/onionoo/server/NodeIndexer.java
index 1229e6b..d380aaa 100644
--- a/src/main/java/org/torproject/onionoo/server/NodeIndexer.java
+++ b/src/main/java/org/torproject/onionoo/server/NodeIndexer.java
@@ -14,11 +14,8 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.File;
-import java.util.ArrayList;
-import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
-import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.SortedMap;
@@ -177,7 +174,6 @@ public class NodeIndexer implements ServletContextListener, Runnable {
}
}
Time time = TimeFactory.getTime();
- List<String> orderRelaysByConsensusWeight = new ArrayList<String>();
/* This variable can go away once all Onionoo services had their
* hourly updater write effective families to summary documents at
* least once. Remove this code after September 8, 2015. */
@@ -188,11 +184,6 @@ public class NodeIndexer implements ServletContextListener, Runnable {
.toUpperCase();
newRelayFingerprintSummaryLines.put(fingerprint, entry);
newRelayFingerprintSummaryLines.put(hashedFingerprint, entry);
- long consensusWeight = entry.getConsensusWeight();
- orderRelaysByConsensusWeight.add(String.format("%020d %s",
- consensusWeight, fingerprint));
- orderRelaysByConsensusWeight.add(String.format("%020d %s",
- consensusWeight, hashedFingerprint));
if (entry.getCountryCode() != null) {
String countryCode = entry.getCountryCode();
if (!newRelaysByCountryCode.containsKey(countryCode)) {
@@ -254,11 +245,6 @@ public class NodeIndexer implements ServletContextListener, Runnable {
newRelaysByContact.get(contact).add(fingerprint);
newRelaysByContact.get(contact).add(hashedFingerprint);
}
- Collections.sort(orderRelaysByConsensusWeight);
- List<String> newRelaysByConsensusWeight = new ArrayList<String>();
- for (String relay : orderRelaysByConsensusWeight) {
- newRelaysByConsensusWeight.add(relay.split(" ")[1]);
- }
/* This loop can go away once all Onionoo services had their hourly
* updater write effective families to summary documents at least
* once. Remove this code after September 8, 2015. */
@@ -313,7 +299,6 @@ public class NodeIndexer implements ServletContextListener, Runnable {
hashedHashedFingerprint);
}
NodeIndex newNodeIndex = new NodeIndex();
- newNodeIndex.setRelaysByConsensusWeight(newRelaysByConsensusWeight);
newNodeIndex.setRelayFingerprintSummaryLines(
newRelayFingerprintSummaryLines);
newNodeIndex.setBridgeFingerprintSummaryLines(
diff --git a/src/main/java/org/torproject/onionoo/server/OrderParameterValues.java b/src/main/java/org/torproject/onionoo/server/OrderParameterValues.java
new file mode 100644
index 0000000..eec47ef
--- /dev/null
+++ b/src/main/java/org/torproject/onionoo/server/OrderParameterValues.java
@@ -0,0 +1,24 @@
+/* Copyright 2017 The Tor Project
+ * See LICENSE for licensing information */
+
+package org.torproject.onionoo.server;
+
+import org.torproject.onionoo.docs.DetailsDocumentFields;
+
+/** Provides constants for order parameter values. */
+public class OrderParameterValues {
+
+ private static final String DESCENDING = "-";
+
+ public static final String FIRST_SEEN_ASC = DetailsDocumentFields.FIRST_SEEN;
+
+ public static final String FIRST_SEEN_DES =
+ DESCENDING + DetailsDocumentFields.FIRST_SEEN;
+
+ public static final String CONSENSUS_WEIGHT_ASC =
+ DetailsDocumentFields.CONSENSUS_WEIGHT;
+
+ public static final String CONSENSUS_WEIGHT_DES =
+ DESCENDING + DetailsDocumentFields.CONSENSUS_WEIGHT;
+}
+
diff --git a/src/main/java/org/torproject/onionoo/server/RequestHandler.java b/src/main/java/org/torproject/onionoo/server/RequestHandler.java
index c94edd4..36d817f 100644
--- a/src/main/java/org/torproject/onionoo/server/RequestHandler.java
+++ b/src/main/java/org/torproject/onionoo/server/RequestHandler.java
@@ -10,6 +10,7 @@ import org.torproject.onionoo.docs.SummaryDocument;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
+import java.util.Comparator;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
@@ -513,34 +514,26 @@ public class RequestHandler {
}
private void order() {
- if (this.order != null && this.order.length == 1) {
- List<String> orderBy = new ArrayList<String>(
- this.nodeIndex.getRelaysByConsensusWeight());
- if (this.order[0].startsWith("-")) {
- Collections.reverse(orderBy);
+ List<SummaryDocument> uniqueRelays = new ArrayList<>();
+ List<SummaryDocument> uniqueBridges = new ArrayList<>();
+ for (SummaryDocument relay : this.filteredRelays.values()) {
+ if (!uniqueRelays.contains(relay)) {
+ uniqueRelays.add(relay);
}
- for (String relay : orderBy) {
- if (this.filteredRelays.containsKey(relay)
- && !this.orderedRelays.contains(filteredRelays.get(relay))) {
- this.orderedRelays.add(this.filteredRelays.remove(relay));
- }
- }
- for (String relay : this.filteredRelays.keySet()) {
- if (!this.orderedRelays.contains(this.filteredRelays.get(relay))) {
- this.orderedRelays.add(this.filteredRelays.remove(relay));
- }
+ }
+ for (SummaryDocument bridge : this.filteredBridges.values()) {
+ if (!uniqueBridges.contains(bridge)) {
+ uniqueBridges.add(bridge);
}
- Set<SummaryDocument> uniqueBridges = new HashSet<SummaryDocument>(
- this.filteredBridges.values());
- this.orderedBridges.addAll(uniqueBridges);
- } else {
- Set<SummaryDocument> uniqueRelays = new HashSet<SummaryDocument>(
- this.filteredRelays.values());
- this.orderedRelays.addAll(uniqueRelays);
- Set<SummaryDocument> uniqueBridges = new HashSet<SummaryDocument>(
- this.filteredBridges.values());
- this.orderedBridges.addAll(uniqueBridges);
}
+ if (this.order != null) {
+ Comparator<SummaryDocument> comparator
+ = new SummaryDocumentComparator(this.order);
+ Collections.sort(uniqueRelays, comparator);
+ Collections.sort(uniqueBridges, comparator);
+ }
+ this.orderedRelays.addAll(uniqueRelays);
+ this.orderedBridges.addAll(uniqueBridges);
}
private void offset() {
diff --git a/src/main/java/org/torproject/onionoo/server/ResourceServlet.java b/src/main/java/org/torproject/onionoo/server/ResourceServlet.java
index 45a52a2..3818731 100644
--- a/src/main/java/org/torproject/onionoo/server/ResourceServlet.java
+++ b/src/main/java/org/torproject/onionoo/server/ResourceServlet.java
@@ -267,16 +267,12 @@ public class ResourceServlet extends HttpServlet {
rh.setContact(contactParts);
}
if (parameterMap.containsKey("order")) {
- String orderParameter = parameterMap.get("order").toLowerCase();
- String orderByField = orderParameter;
- if (orderByField.startsWith("-")) {
- orderByField = orderByField.substring(1);
- }
- if (!orderByField.equals("consensus_weight")) {
+ String[] order = this.parseOrderParameter(parameterMap.get("order"));
+ if (order == null) {
response.sendError(HttpServletResponse.SC_BAD_REQUEST);
return;
}
- rh.setOrder(new String[] { orderParameter });
+ rh.setOrder(order);
}
if (parameterMap.containsKey("offset")) {
String offsetParameter = parameterMap.get("offset");
@@ -483,6 +479,36 @@ public class ResourceServlet extends HttpServlet {
return parameter.split(" ");
}
+ private static Pattern orderParameterPattern =
+ Pattern.compile("^[0-9a-zA-Z_,-]*$");
+
+ private static HashSet<String> knownOrderParameters = new HashSet<>(
+ Arrays.asList(new String[] { OrderParameterValues.CONSENSUS_WEIGHT_ASC,
+ OrderParameterValues.CONSENSUS_WEIGHT_DES,
+ OrderParameterValues.FIRST_SEEN_ASC,
+ OrderParameterValues.FIRST_SEEN_DES }));
+
+ private String[] parseOrderParameter(String parameter) {
+ if (!orderParameterPattern.matcher(parameter).matches()) {
+ /* Orders contain illegal character(s). */
+ return null;
+ }
+ String[] orderParameters = parameter.toLowerCase().split(",");
+ Set<String> seenOrderParameters = new HashSet<>();
+ for (String orderParameter : orderParameters) {
+ if (!knownOrderParameters.contains(orderParameter)) {
+ /* Unknown order parameter. */
+ return null;
+ }
+ if (!seenOrderParameters.add(orderParameter.startsWith("-")
+ ? orderParameter.substring(1) : orderParameter)) {
+ /* Duplicate parameter. */
+ return null;
+ }
+ }
+ return orderParameters;
+ }
+
private static Pattern fieldsParameterPattern =
Pattern.compile("^[0-9a-zA-Z_,]*$");
diff --git a/src/main/java/org/torproject/onionoo/server/ResponseBuilder.java b/src/main/java/org/torproject/onionoo/server/ResponseBuilder.java
index bb532f6..1986784 100644
--- a/src/main/java/org/torproject/onionoo/server/ResponseBuilder.java
+++ b/src/main/java/org/torproject/onionoo/server/ResponseBuilder.java
@@ -6,6 +6,7 @@ package org.torproject.onionoo.server;
import org.torproject.onionoo.docs.BandwidthDocument;
import org.torproject.onionoo.docs.ClientsDocument;
import org.torproject.onionoo.docs.DetailsDocument;
+import org.torproject.onionoo.docs.DetailsDocumentFields;
import org.torproject.onionoo.docs.DocumentStore;
import org.torproject.onionoo.docs.DocumentStoreFactory;
import org.torproject.onionoo.docs.SummaryDocument;
@@ -77,7 +78,7 @@ public class ResponseBuilder {
return this.charsWritten;
}
- private static final String PROTOCOL_VERSION = "3.1";
+ private static final String PROTOCOL_VERSION = "3.2";
private static final String NEXT_MAJOR_VERSION_SCHEDULED = null;
@@ -205,7 +206,7 @@ public class ResponseBuilder {
} else if (field.equals("last_changed_address_or_port")) {
dd.setLastChangedAddressOrPort(
detailsDocument.getLastChangedAddressOrPort());
- } else if (field.equals("first_seen")) {
+ } else if (field.equals(DetailsDocumentFields.FIRST_SEEN)) {
dd.setFirstSeen(detailsDocument.getFirstSeen());
} else if (field.equals("running")) {
dd.setRunning(detailsDocument.getRunning());
@@ -227,7 +228,7 @@ public class ResponseBuilder {
dd.setAsNumber(detailsDocument.getAsNumber());
} else if (field.equals("as_name")) {
dd.setAsName(detailsDocument.getAsName());
- } else if (field.equals("consensus_weight")) {
+ } else if (field.equals(DetailsDocumentFields.CONSENSUS_WEIGHT)) {
dd.setConsensusWeight(detailsDocument.getConsensusWeight());
} else if (field.equals("host_name")) {
dd.setHostName(detailsDocument.getHostName());
diff --git a/src/main/java/org/torproject/onionoo/server/SummaryDocumentComparator.java b/src/main/java/org/torproject/onionoo/server/SummaryDocumentComparator.java
new file mode 100644
index 0000000..64f61cc
--- /dev/null
+++ b/src/main/java/org/torproject/onionoo/server/SummaryDocumentComparator.java
@@ -0,0 +1,51 @@
+/* Copyright 2017 The Tor Project
+ * See LICENSE for licensing information */
+
+package org.torproject.onionoo.server;
+
+import org.torproject.onionoo.docs.SummaryDocument;
+
+import java.util.Comparator;
+
+public class SummaryDocumentComparator implements Comparator<SummaryDocument> {
+
+ private final String[] orderParameters;
+
+ /** Comparator is initialized with the order parameters. */
+ public SummaryDocumentComparator(String ... orderParameters) {
+ this.orderParameters = orderParameters;
+ }
+
+ @Override
+ public int compare(SummaryDocument o1, SummaryDocument o2) {
+ int result = 0;
+ for (String orderParameter : orderParameters) {
+ switch (orderParameter) {
+ case OrderParameterValues.CONSENSUS_WEIGHT_ASC:
+ result = Long.compare(o1.getConsensusWeight(),
+ o2.getConsensusWeight());
+ break;
+ case OrderParameterValues.CONSENSUS_WEIGHT_DES:
+ result = Long.compare(o2.getConsensusWeight(),
+ o1.getConsensusWeight());
+ break;
+ case OrderParameterValues.FIRST_SEEN_ASC:
+ result = Long.compare(o1.getFirstSeenMillis(),
+ o2.getFirstSeenMillis());
+ break;
+ case OrderParameterValues.FIRST_SEEN_DES:
+ result = Long.compare(o2.getFirstSeenMillis(),
+ o1.getFirstSeenMillis());
+ break;
+ default:
+ throw new RuntimeException("Invalid order parameter: "
+ + orderParameter + ". Check initialization of this class!");
+ }
+ if (result != 0) {
+ break;
+ }
+ }
+ return result;
+ }
+}
+
diff --git a/src/main/resources/web/protocol.html b/src/main/resources/web/protocol.html
index 6e8dc34..f13e41c 100644
--- a/src/main/resources/web/protocol.html
+++ b/src/main/resources/web/protocol.html
@@ -187,6 +187,8 @@ documents on August 25, 2015.</li>
characters of a space-separated fingerprint on November 15, 2015.</li>
<li><strong>3.1</strong>: Removed optional "family" field on January 18,
2016.</li>
+<li><strong>3.2</strong>: Extended order parameter to "first_seen" on
+January 11, 2017.</li>
</ul>
</div> <!-- box -->
@@ -473,10 +475,13 @@ Re-order results by a comma-separated list
of fields in ascending or descending order.
Results are first ordered by the first list element, then by the second,
and so on.
-Possible fields for ordering are: <strong>consensus_weight</strong>.
+Possible fields for ordering are: <strong>consensus_weight</strong> and
+<strong>first_seen</strong>.
Field names are case-insensitive.
Ascending order is the default; descending order is selected by prepending
fields with a minus sign (<strong>-</strong>).
+Field names can be listed at most once in either ascending or descending
+order.
Relays or bridges which don't have any value for a field to be ordered by
are always appended to the end, regardless or sorting order.
The ordering is defined independent of the requested document type and
diff --git a/src/test/java/org/torproject/onionoo/server/ResourceServletTest.java b/src/test/java/org/torproject/onionoo/server/ResourceServletTest.java
index f17e228..e7358ea 100644
--- a/src/test/java/org/torproject/onionoo/server/ResourceServletTest.java
+++ b/src/test/java/org/torproject/onionoo/server/ResourceServletTest.java
@@ -1123,9 +1123,9 @@ public class ResourceServletTest {
}
@Test()
- public void testFirstSeenDaysSixToSixteen() {
+ public void testFirstSeenDaysSevenToSixteen() {
this.assertSummaryDocument(
- "/summary?first_seen_days=6-16", 2, null, 1, null);
+ "/summary?first_seen_days=7-16", 2, null, 1, null);
}
@Test()
@@ -1253,7 +1253,7 @@ public class ResourceServletTest {
@Test()
public void testOrderConsensusWeightAscending() {
this.assertSummaryDocument(
- "/summary?order=consensus_weight", 3,
+ "/summary?order=" + OrderParameterValues.CONSENSUS_WEIGHT_ASC, 3,
new String[] { "TorkaZ", "TimMayTribute", "Ferrari458" }, 3,
null);
}
@@ -1261,7 +1261,7 @@ public class ResourceServletTest {
@Test()
public void testOrderConsensusWeightDescending() {
this.assertSummaryDocument(
- "/summary?order=-consensus_weight", 3,
+ "/summary?order=" + OrderParameterValues.CONSENSUS_WEIGHT_DES, 3,
new String[] { "Ferrari458", "TimMayTribute", "TorkaZ" }, 3,
null);
}
@@ -1269,13 +1269,15 @@ public class ResourceServletTest {
@Test()
public void testOrderConsensusWeightAscendingTwice() {
this.assertErrorStatusCode(
- "/summary?order=consensus_weight,consensus_weight", 400);
+ "/summary?order=" + OrderParameterValues.CONSENSUS_WEIGHT_ASC
+ + "," + OrderParameterValues.CONSENSUS_WEIGHT_ASC, 400);
}
@Test()
public void testOrderConsensusWeightAscendingThenDescending() {
this.assertErrorStatusCode(
- "/summary?order=consensus_weight,-consensus_weight", 400);
+ "/summary?order=" + OrderParameterValues.CONSENSUS_WEIGHT_ASC + ","
+ + OrderParameterValues.CONSENSUS_WEIGHT_DES + "", 400);
}
@Test()
@@ -1295,18 +1297,57 @@ public class ResourceServletTest {
@Test()
public void testOrderConsensusWeightAscendingLimit1() {
this.assertSummaryDocument(
- "/summary?order=consensus_weight&limit=1", 1,
+ "/summary?order=" + OrderParameterValues.CONSENSUS_WEIGHT_ASC
+ + "&limit=1", 1,
new String[] { "TorkaZ" }, 0, null);
}
@Test()
- public void testOrderConsensusWeightDecendingLimit1() {
+ public void testOrderConsensusWeightDescendingLimit1() {
this.assertSummaryDocument(
- "/summary?order=-consensus_weight&limit=1", 1,
+ "/summary?order=" + OrderParameterValues.CONSENSUS_WEIGHT_DES
+ + "&limit=1", 1,
new String[] { "Ferrari458" }, 0, null);
}
@Test()
+ public void testOrderConsensusWeightFiveTimes() {
+ this.assertErrorStatusCode(
+ "/summary?order=" + OrderParameterValues.CONSENSUS_WEIGHT_ASC + ","
+ + OrderParameterValues.CONSENSUS_WEIGHT_ASC + ","
+ + OrderParameterValues.CONSENSUS_WEIGHT_ASC + ","
+ + OrderParameterValues.CONSENSUS_WEIGHT_ASC + ","
+ + OrderParameterValues.CONSENSUS_WEIGHT_ASC, 400);
+ }
+
+ @Test()
+ public void testOrderFirstSeenThenConsensusWeight() {
+ this.assertSummaryDocument(
+ "/summary?order=" + OrderParameterValues.FIRST_SEEN_ASC + ","
+ + OrderParameterValues.CONSENSUS_WEIGHT_ASC, 3,
+ new String[] { "TimMayTribute", "Ferrari458", "TorkaZ" }, 3,
+ new String[] { "gummy", null, "ec2bridgercc7f31fe" });
+ }
+
+ @Test()
+ public void testOrderFirstSeenDescendingThenConsensusWeight() {
+ this.assertSummaryDocument("/summary?order="
+ + OrderParameterValues.FIRST_SEEN_DES + ","
+ + OrderParameterValues.CONSENSUS_WEIGHT_ASC, 3,
+ new String[] { "TorkaZ", "TimMayTribute", "Ferrari458" }, 3,
+ new String[] { "ec2bridgercc7f31fe", null, "gummy" });
+ }
+
+ @Test()
+ public void testOrderConsensusWeightThenFirstSeenDescending() {
+ this.assertSummaryDocument(
+ "/summary?order=" + OrderParameterValues.CONSENSUS_WEIGHT_ASC + ","
+ + OrderParameterValues.FIRST_SEEN_DES, 3,
+ new String[] { "TorkaZ", "TimMayTribute", "Ferrari458" }, 3,
+ null);
+ }
+
+ @Test()
public void testOffsetOne() {
this.assertSummaryDocument(
"/summary?offset=1", 2, null, 3, null);
diff --git a/src/test/java/org/torproject/onionoo/server/SummaryDocumentComparatorTest.java b/src/test/java/org/torproject/onionoo/server/SummaryDocumentComparatorTest.java
new file mode 100644
index 0000000..c1d909f
--- /dev/null
+++ b/src/test/java/org/torproject/onionoo/server/SummaryDocumentComparatorTest.java
@@ -0,0 +1,105 @@
+/* Copyright 2017 The Tor Project
+ * See LICENSE for licensing information */
+
+package org.torproject.onionoo.server;
+
+import static org.junit.Assert.assertEquals;
+
+import org.torproject.onionoo.docs.DateTimeHelper;
+import org.torproject.onionoo.docs.DetailsDocumentFields;
+import org.torproject.onionoo.docs.SummaryDocument;
+
+import org.hamcrest.Matchers;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.ExpectedException;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+import org.junit.runners.Parameterized.Parameters;
+
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.TreeSet;
+
+ at RunWith(Parameterized.class)
+public class SummaryDocumentComparatorTest {
+
+ @Rule
+ public ExpectedException thrown = ExpectedException.none();
+
+ private SummaryDocument createSummaryDoc() {
+ return new SummaryDocument(true, "TorkaZ",
+ "000C5F55BD4814B917CC474BD537F1A3B33CCE2A", Arrays.asList(
+ new String[] { "62.216.201.221", "62.216.201.222",
+ "62.216.201.223" }), DateTimeHelper.parse("2013-04-19 05:00:00"),
+ false, new TreeSet<>(Arrays.asList(new String[] { "Running",
+ "Valid" })), 20L, "de",
+ DateTimeHelper.parse("2013-04-18 05:00:00"), "AS8767",
+ "torkaz <klaus dot zufall at gmx dot de> "
+ + "<fb-token:np5_g_83jmf=>", new TreeSet<>(Arrays.asList(
+ new String[] { "001C13B3A55A71B977CA65EC85539D79C653A3FC",
+ "0025C136C1F3A9EEFE2AE3F918F03BFA21B5070B" })),
+ new TreeSet<>(Arrays.asList(
+ new String[] { "001C13B3A55A71B977CA65EC85539D79C653A3FC" })));
+ }
+
+ /** Some values for running all comparison types. */
+ @Parameters
+ public static Collection<Object[]> data() {
+ return Arrays.asList(new Object[][] {
+ {OrderParameterValues.FIRST_SEEN_ASC, new long[]{1234L, 85968L}},
+ {OrderParameterValues.FIRST_SEEN_DES, new long[]{12345L, 859689L}},
+ {OrderParameterValues.CONSENSUS_WEIGHT_ASC, new long[]{12340L, 85968L}},
+ {OrderParameterValues.CONSENSUS_WEIGHT_DES, new long[]{1234L, 59680L}},
+ {OrderParameterValues.FIRST_SEEN_ASC, new long[]{91234L, 5968L}},
+ {OrderParameterValues.FIRST_SEEN_DES, new long[]{912345L, 59689L}},
+ {OrderParameterValues.CONSENSUS_WEIGHT_ASC, new long[]{912340L, 5968L}},
+ {OrderParameterValues.CONSENSUS_WEIGHT_DES, new long[]{91234L, 59680L}},
+ {OrderParameterValues.FIRST_SEEN_ASC, new long[]{1234L, 1234L}},
+ {OrderParameterValues.FIRST_SEEN_DES, new long[]{12345L, 12345L}},
+ {OrderParameterValues.CONSENSUS_WEIGHT_ASC, new long[]{12340L, 12340L}},
+ {OrderParameterValues.CONSENSUS_WEIGHT_DES, new long[]{1234L, 1234L}}
+ }
+ );
+ }
+
+ private SummaryDocument[] sd = new SummaryDocument[2];
+ private String order;
+ private int expected;
+
+ /** This constructor receives the above defined data for each run. */
+ public SummaryDocumentComparatorTest(String order, long[] vals) {
+ for (int i = 0; i < sd.length; i++) {
+ sd[i] = createSummaryDoc();
+ if (order.contains(DetailsDocumentFields.FIRST_SEEN)) {
+ sd[i].setFirstSeenMillis(vals[i]);
+ } else {
+ sd[i].setConsensusWeight(vals[i]);
+ }
+ }
+ this.order = order;
+ this.expected = Long.compare(vals[0], vals[1]);
+ if (order.contains("-")) {
+ this.expected = - this.expected;
+ }
+ }
+
+ @Test()
+ public void testInvalidParameter() {
+ String[] dummy = {OrderParameterValues.FIRST_SEEN_DES, "odd parameter"};
+ thrown.expect(RuntimeException.class);
+ thrown.expectMessage(Matchers
+ .allOf(Matchers.containsString("Invalid order parameter"),
+ Matchers.containsString(dummy[1])));
+ SummaryDocumentComparator sdc = new SummaryDocumentComparator(dummy);
+ sdc.compare(createSummaryDoc(), createSummaryDoc());
+ }
+
+ @Test()
+ public void testRegularComparisons() {
+ SummaryDocumentComparator sdc
+ = new SummaryDocumentComparator(this.order);
+ assertEquals(this.expected, sdc.compare(this.sd[0], this.sd[1]));
+ }
+
+}
More information about the tor-commits
mailing list