aboutsummaryrefslogtreecommitdiff
path: root/okhttp-hpacktests
diff options
context:
space:
mode:
authorNeil Fuller <nfuller@google.com>2015-01-20 09:39:41 +0000
committerNeil Fuller <nfuller@google.com>2015-01-20 12:01:46 +0000
commite78f117bcbd6b57d783737107f445ef75ecb474a (patch)
tree6aeb5ecee431742785d8196f39eace37c7a87e63 /okhttp-hpacktests
parent686cfbde70b55b77360f3401dedf580eea6d47f9 (diff)
downloadokhttp-e78f117bcbd6b57d783737107f445ef75ecb474a.tar.gz
Pull latest OkHttp code from upstream
okio: okio is now managed upstream as a separate project but has been included here as a sub directory: the okio version here is intended only for use with OkHttp. okio is synced to upstream commit 82358df7f09e18aa42348836c614212085bbf045. See okio/README.android for local changed needed to make it compile. okhttp: This is effectively an upgrade from a snapshot close to OkHttp 1.5 with Android additions to a snapshot close to OkHttp 2.2. okhttp was synced to upstream commit 0a197466608681593cc9be9487965a0b1d5c244c See README.android for local changes needed to make it compile. Most of the old Android changes have been pushed upstream and other upstream changes have been made to keep OkHttp working on Android. TLS fallback changes have not been upstreamed yet: bcce0a3d26d66d33beb742ae2adddb3b7db5ad08 ede2bf1af0917482da8ccb7b048130592034253d This means that some CTS tests will start to fail. A later commit will fix those changes when it has been accepted upstream. There are associated changes in libcore and frameworks/base. Change-Id: I0a68b27b1ec7067be452671bc591edfd84e310f2
Diffstat (limited to 'okhttp-hpacktests')
-rw-r--r--okhttp-hpacktests/README.md19
-rw-r--r--okhttp-hpacktests/pom.xml56
-rw-r--r--okhttp-hpacktests/src/test/java/com/squareup/okhttp/internal/spdy/HpackDecodeInteropTest.java42
-rw-r--r--okhttp-hpacktests/src/test/java/com/squareup/okhttp/internal/spdy/HpackDecodeTestBase.java92
-rw-r--r--okhttp-hpacktests/src/test/java/com/squareup/okhttp/internal/spdy/HpackRoundTripTest.java63
-rw-r--r--okhttp-hpacktests/src/test/java/com/squareup/okhttp/internal/spdy/hpackjson/Case.java69
-rw-r--r--okhttp-hpacktests/src/test/java/com/squareup/okhttp/internal/spdy/hpackjson/HpackJsonUtil.java88
-rw-r--r--okhttp-hpacktests/src/test/java/com/squareup/okhttp/internal/spdy/hpackjson/Story.java66
8 files changed, 495 insertions, 0 deletions
diff --git a/okhttp-hpacktests/README.md b/okhttp-hpacktests/README.md
new file mode 100644
index 0000000..6b85c9a
--- /dev/null
+++ b/okhttp-hpacktests/README.md
@@ -0,0 +1,19 @@
+OkHttp HPACK tests
+==================
+
+These tests use the [hpack-test-case][1] project to validate OkHttp's HPACK
+implementation. The HPACK test cases are in a separate git submodule, so to
+initialize them, you must run:
+
+ git submodule init
+ git submodule update
+
+TODO
+----
+
+ * Add maven goal to avoid manual call to git submodule init.
+ * Make hpack-test-case update itself from git, and run new tests.
+ * Add maven goal to generate stories and a pull request to hpack-test-case
+ to have others validate our output.
+
+[1]: https://github.com/http2jp/hpack-test-case
diff --git a/okhttp-hpacktests/pom.xml b/okhttp-hpacktests/pom.xml
new file mode 100644
index 0000000..70a59f2
--- /dev/null
+++ b/okhttp-hpacktests/pom.xml
@@ -0,0 +1,56 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
+ <parent>
+ <groupId>com.squareup.okhttp</groupId>
+ <artifactId>parent</artifactId>
+ <version>2.2.0-SNAPSHOT</version>
+ </parent>
+
+ <artifactId>okhttp-hpacktests</artifactId>
+ <name>OkHttp HPACK Tests</name>
+
+ <dependencies>
+ <dependency>
+ <groupId>com.squareup.okio</groupId>
+ <artifactId>okio</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>com.squareup.okhttp</groupId>
+ <artifactId>okhttp</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>junit</groupId>
+ <artifactId>junit</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>com.squareup.okhttp</groupId>
+ <artifactId>mockwebserver</artifactId>
+ <version>${project.version}</version>
+ <scope>test</scope>
+ </dependency>
+ <!-- Gson: Java to Json conversion -->
+ <dependency>
+ <groupId>com.google.code.gson</groupId>
+ <artifactId>gson</artifactId>
+ <scope>compile</scope>
+ </dependency>
+ </dependencies>
+
+ <build>
+ <plugins>
+ <!-- Do not deploy this as an artifact to Maven central. -->
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-deploy-plugin</artifactId>
+ <configuration>
+ <skip>true</skip>
+ </configuration>
+ </plugin>
+ </plugins>
+ </build>
+</project>
diff --git a/okhttp-hpacktests/src/test/java/com/squareup/okhttp/internal/spdy/HpackDecodeInteropTest.java b/okhttp-hpacktests/src/test/java/com/squareup/okhttp/internal/spdy/HpackDecodeInteropTest.java
new file mode 100644
index 0000000..30e1a7b
--- /dev/null
+++ b/okhttp-hpacktests/src/test/java/com/squareup/okhttp/internal/spdy/HpackDecodeInteropTest.java
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2014 Square, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.squareup.okhttp.internal.spdy;
+
+import com.squareup.okhttp.internal.spdy.hpackjson.Story;
+import java.util.Collection;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+
+import static com.squareup.okhttp.internal.spdy.hpackjson.HpackJsonUtil.storiesForCurrentDraft;
+
+@RunWith(Parameterized.class)
+public class HpackDecodeInteropTest extends HpackDecodeTestBase {
+
+ public HpackDecodeInteropTest(Story story) {
+ super(story);
+ }
+
+ @Parameterized.Parameters(name="{0}")
+ public static Collection<Story[]> createStories() throws Exception {
+ return createStories(storiesForCurrentDraft());
+ }
+
+ @Test
+ public void testGoodDecoderInterop() throws Exception {
+ testDecoder();
+ }
+}
diff --git a/okhttp-hpacktests/src/test/java/com/squareup/okhttp/internal/spdy/HpackDecodeTestBase.java b/okhttp-hpacktests/src/test/java/com/squareup/okhttp/internal/spdy/HpackDecodeTestBase.java
new file mode 100644
index 0000000..1bd9b00
--- /dev/null
+++ b/okhttp-hpacktests/src/test/java/com/squareup/okhttp/internal/spdy/HpackDecodeTestBase.java
@@ -0,0 +1,92 @@
+/*
+ * Copyright (C) 2014 Square, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.squareup.okhttp.internal.spdy;
+
+import com.squareup.okhttp.internal.spdy.hpackjson.Case;
+import com.squareup.okhttp.internal.spdy.hpackjson.HpackJsonUtil;
+import com.squareup.okhttp.internal.spdy.hpackjson.Story;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.LinkedHashSet;
+import java.util.List;
+import okio.Buffer;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.fail;
+
+/**
+ * Tests Hpack implementation using https://github.com/http2jp/hpack-test-case/
+ */
+public class HpackDecodeTestBase {
+
+ /**
+ * Reads all stories in the folders provided, asserts if no story found.
+ */
+ protected static Collection<Story[]> createStories(String[] interopTests)
+ throws Exception {
+ List<Story[]> result = new ArrayList<>();
+ for (String interopTestName : interopTests) {
+ List<Story> stories = HpackJsonUtil.readStories(interopTestName);
+ if (stories.isEmpty()) {
+ fail("No stories for: " + interopTestName);
+ }
+ for (Story story : stories) {
+ result.add(new Story[] { story });
+ }
+ }
+ return result;
+ }
+
+ private final Buffer bytesIn = new Buffer();
+ private final HpackDraft10.Reader hpackReader = new HpackDraft10.Reader(4096, bytesIn);
+
+ private final Story story;
+
+ public HpackDecodeTestBase(Story story) {
+ this.story = story;
+ }
+
+ /**
+ * Expects wire to be set for all cases, and compares the decoder's output to
+ * expected headers.
+ */
+ protected void testDecoder() throws Exception {
+ testDecoder(story);
+ }
+
+ protected void testDecoder(Story story) throws Exception {
+ for (Case caze : story.getCases()) {
+ bytesIn.write(caze.getWire());
+ hpackReader.readHeaders();
+ assertSetEquals(String.format("seqno=%d", caze.getSeqno()), caze.getHeaders(),
+ hpackReader.getAndResetHeaderList());
+ }
+ }
+ /**
+ * Checks if {@code expected} and {@code observed} are equal when viewed as a
+ * set and headers are deduped.
+ *
+ * TODO: See if duped headers should be preserved on decode and verify.
+ */
+ private static void assertSetEquals(
+ String message, List<Header> expected, List<Header> observed) {
+ assertEquals(message, new LinkedHashSet<>(expected), new LinkedHashSet<>(observed));
+ }
+
+ protected Story getStory() {
+ return story;
+ }
+}
diff --git a/okhttp-hpacktests/src/test/java/com/squareup/okhttp/internal/spdy/HpackRoundTripTest.java b/okhttp-hpacktests/src/test/java/com/squareup/okhttp/internal/spdy/HpackRoundTripTest.java
new file mode 100644
index 0000000..a78dab5
--- /dev/null
+++ b/okhttp-hpacktests/src/test/java/com/squareup/okhttp/internal/spdy/HpackRoundTripTest.java
@@ -0,0 +1,63 @@
+/*
+ * Copyright (C) 2014 Square, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.squareup.okhttp.internal.spdy;
+
+import com.squareup.okhttp.internal.spdy.hpackjson.Case;
+import com.squareup.okhttp.internal.spdy.hpackjson.Story;
+import okio.Buffer;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+
+import java.util.Collection;
+
+/**
+ * Tests for round-tripping headers through hpack..
+ */
+// TODO: update hpack-test-case with the output of our encoder.
+// This test will hide complementary bugs in the encoder and decoder,
+// We should test that the encoder is producing responses that are
+// d]
+@RunWith(Parameterized.class)
+public class HpackRoundTripTest extends HpackDecodeTestBase {
+
+ private static final String[] RAW_DATA = { "raw-data" };
+
+ @Parameterized.Parameters(name="{0}")
+ public static Collection<Story[]> getStories() throws Exception {
+ return createStories(RAW_DATA);
+ }
+
+ private Buffer bytesOut = new Buffer();
+ private HpackDraft10.Writer hpackWriter = new HpackDraft10.Writer(bytesOut);
+
+ public HpackRoundTripTest(Story story) {
+ super(story);
+ }
+
+ @Test
+ public void testRoundTrip() throws Exception {
+ Story story = getStory().clone();
+ // Mutate cases in base class.
+ for (Case caze : story.getCases()) {
+ hpackWriter.writeHeaders(caze.getHeaders());
+ caze.setWire(bytesOut.readByteString());
+ }
+
+ testDecoder(story);
+ }
+
+}
diff --git a/okhttp-hpacktests/src/test/java/com/squareup/okhttp/internal/spdy/hpackjson/Case.java b/okhttp-hpacktests/src/test/java/com/squareup/okhttp/internal/spdy/hpackjson/Case.java
new file mode 100644
index 0000000..d5d2728
--- /dev/null
+++ b/okhttp-hpacktests/src/test/java/com/squareup/okhttp/internal/spdy/hpackjson/Case.java
@@ -0,0 +1,69 @@
+/*
+ * Copyright (C) 2014 Square, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.squareup.okhttp.internal.spdy.hpackjson;
+
+import com.squareup.okhttp.internal.spdy.Header;
+import okio.ByteString;
+
+import java.util.ArrayList;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * Representation of an individual case (set of headers and wire format).
+ * There are many cases for a single story. This class is used reflectively
+ * with Gson to parse stories.
+ */
+public class Case implements Cloneable {
+
+ private int seqno;
+ private String wire;
+ private List<Map<String, String>> headers;
+
+ public List<Header> getHeaders() {
+ List<Header> result = new ArrayList<>();
+ for (Map<String, String> inputHeader : headers) {
+ Map.Entry<String, String> entry = inputHeader.entrySet().iterator().next();
+ result.add(new Header(entry.getKey(), entry.getValue()));
+ }
+ return result;
+ }
+
+ public ByteString getWire() {
+ return ByteString.decodeHex(wire);
+ }
+
+ public int getSeqno() {
+ return seqno;
+ }
+
+ public void setWire(ByteString wire) {
+ this.wire = wire.hex();
+ }
+
+ @Override
+ protected Case clone() throws CloneNotSupportedException {
+ Case result = new Case();
+ result.seqno = seqno;
+ result.wire = wire;
+ result.headers = new ArrayList<>();
+ for (Map<String, String> header : headers) {
+ result.headers.add(new LinkedHashMap<String, String>(header));
+ }
+ return result;
+ }
+}
diff --git a/okhttp-hpacktests/src/test/java/com/squareup/okhttp/internal/spdy/hpackjson/HpackJsonUtil.java b/okhttp-hpacktests/src/test/java/com/squareup/okhttp/internal/spdy/hpackjson/HpackJsonUtil.java
new file mode 100644
index 0000000..9d721ab
--- /dev/null
+++ b/okhttp-hpacktests/src/test/java/com/squareup/okhttp/internal/spdy/hpackjson/HpackJsonUtil.java
@@ -0,0 +1,88 @@
+/*
+ * Copyright (C) 2014 Square, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.squareup.okhttp.internal.spdy.hpackjson;
+
+import com.google.gson.Gson;
+import com.google.gson.GsonBuilder;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.net.URISyntaxException;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+/**
+ * Utilities for reading HPACK tests.
+ */
+public final class HpackJsonUtil {
+ private static final int CURRENT_DRAFT = 9;
+
+ private static final String STORY_RESOURCE_FORMAT = "/hpack-test-case/%s/story_%02d.json";
+
+ private static final Gson GSON = new GsonBuilder().create();
+
+ private static Story readStory(InputStream jsonResource) throws IOException {
+ return GSON.fromJson(new InputStreamReader(jsonResource, "UTF-8"), Story.class);
+ }
+
+ /** Iterate through the hpack-test-case resources, only picking stories for the current draft. */
+ public static String[] storiesForCurrentDraft() throws URISyntaxException {
+ File testCaseDirectory = new File(HpackJsonUtil.class.getResource("/hpack-test-case").toURI());
+ List<String> storyNames = new ArrayList<String>();
+ for (File path : testCaseDirectory.listFiles()) {
+ if (path.isDirectory() && Arrays.asList(path.list()).contains("story_00.json")) {
+ try {
+ Story firstStory = readStory(new FileInputStream(new File(path, "story_00.json")));
+ if (firstStory.getDraft() == CURRENT_DRAFT) {
+ storyNames.add(path.getName());
+ }
+ } catch (IOException ignored) {
+ // Skip this path.
+ }
+ }
+ }
+ return storyNames.toArray(new String[storyNames.size()]);
+ }
+
+ /**
+ * Reads stories named "story_xx.json" from the folder provided.
+ */
+ public static List<Story> readStories(String testFolderName) throws Exception {
+ List<Story> result = new ArrayList<>();
+ int i = 0;
+ while (true) { // break after last test.
+ String storyResourceName = String.format(STORY_RESOURCE_FORMAT, testFolderName, i);
+ InputStream storyInputStream = HpackJsonUtil.class.getResourceAsStream(storyResourceName);
+ if (storyInputStream == null) {
+ break;
+ }
+ try {
+ Story story = readStory(storyInputStream);
+ story.setFileName(storyResourceName);
+ result.add(story);
+ i++;
+ } finally {
+ storyInputStream.close();
+ }
+ }
+ return result;
+ }
+
+ private HpackJsonUtil() { } // Utilities only.
+} \ No newline at end of file
diff --git a/okhttp-hpacktests/src/test/java/com/squareup/okhttp/internal/spdy/hpackjson/Story.java b/okhttp-hpacktests/src/test/java/com/squareup/okhttp/internal/spdy/hpackjson/Story.java
new file mode 100644
index 0000000..5ff2b07
--- /dev/null
+++ b/okhttp-hpacktests/src/test/java/com/squareup/okhttp/internal/spdy/hpackjson/Story.java
@@ -0,0 +1,66 @@
+/*
+ * Copyright (C) 2014 Square, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.squareup.okhttp.internal.spdy.hpackjson;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Representation of one story, a set of request headers to encode or decode.
+ * This class is used reflectively with Gson to parse stories from files.
+ */
+public class Story implements Cloneable {
+
+ private transient String fileName;
+ private List<Case> cases;
+ private int draft;
+ private String description;
+
+ /**
+ * The filename is only used in the toString representation.
+ */
+ void setFileName(String fileName) {
+ this.fileName = fileName;
+ }
+
+ public List<Case> getCases() {
+ return cases;
+ }
+
+ /** We only expect stories that match the draft we've implemented to pass. */
+ public int getDraft() {
+ return draft;
+ }
+
+ @Override
+ public Story clone() throws CloneNotSupportedException {
+ Story story = new Story();
+ story.fileName = this.fileName;
+ story.cases = new ArrayList<>();
+ for (Case caze : cases) {
+ story.cases.add(caze.clone());
+ }
+ story.draft = draft;
+ story.description = description;
+ return story;
+ }
+
+ @Override
+ public String toString() {
+ // Used as the test name.
+ return fileName;
+ }
+}