Skip to content

Commit 9daa0e3

Browse files
authored
Merge pull request #15 from taskcluster/bug1492543
Bug 1492543 - Treat leading/trailing slashes equivalently between implementations
2 parents fa45862 + 6c5f514 commit 9daa0e3

File tree

12 files changed

+241
-230
lines changed

12 files changed

+241
-230
lines changed

pom.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -153,7 +153,7 @@
153153
<testResource>
154154
<directory>.</directory>
155155
<includes>
156-
<include>specification.yml</include>
156+
<include>tests.yml</include>
157157
</includes>
158158
</testResource>
159159
</testResources>

specification.yml

Lines changed: 0 additions & 71 deletions
This file was deleted.

src/index.js

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,8 @@ const assert = require('assert');
22

33
const TASKCLUSTER_NET = 'https://taskcluster.net';
44

5-
const cleanRoot = rootUrl => rootUrl.replace(/\/$/, '');
6-
const cleanPath = path => path.replace(/^\//, '');
5+
const cleanRoot = rootUrl => rootUrl.replace(/\/*$/, '');
6+
const cleanPath = path => path.replace(/^\/*/, '');
77

88
class LegacyUrls {
99
/**
@@ -61,7 +61,6 @@ class LegacyUrls {
6161

6262
class Urls {
6363
constructor(rootUrl) {
64-
assert(rootUrl, 'no rootUrl provided');
6564
this.rootUrl = cleanRoot(rootUrl);
6665
}
6766

src/main/java/org/mozilla/taskcluster/urls/Clean.java

Lines changed: 2 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -6,16 +6,10 @@ private Clean() {
66
}
77

88
public static String path(String path) {
9-
if (path.startsWith("/")) {
10-
return path.substring(1);
11-
}
12-
return path;
9+
return path.replaceAll("^/*", "");
1310
}
1411

1512
public static String url(String url) {
16-
if (url.endsWith("/")) {
17-
return url.substring(0, url.length() - 1);
18-
}
19-
return url;
13+
return url.replaceAll("/*$", "");
2014
}
2115
}
Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
11
package org.mozilla.taskcluster.urls;
22

3+
import java.util.Map;
34
import lombok.Data;
45

56
@Data
67
public class TestCase {
7-
private String type;
8-
private String expectedUrl;
9-
private String oldExpectedUrl;
10-
private String[][] argSets;
8+
private String function;
9+
private Map<String, String> expected;
10+
private String[][] argSets;
1111
}

src/test/java/org/mozilla/taskcluster/urls/TestCases.java

Lines changed: 0 additions & 8 deletions
This file was deleted.
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
package org.mozilla.taskcluster.urls;
2+
3+
import java.util.Map;
4+
import lombok.Data;
5+
6+
@Data
7+
public class TestsSpecification {
8+
private TestCase[] tests;
9+
private Map<String, String[]> rootURLs;
10+
}

src/test/java/org/mozilla/taskcluster/urls/URLsTest.java

Lines changed: 16 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
import java.io.InputStream;
44
import java.io.IOException;
5+
import java.util.Map;
56

67
import org.junit.Assert;
78
import org.junit.Test;
@@ -11,40 +12,29 @@
1112

1213
public class URLsTest {
1314

14-
private final static String[] oldRootURLs = new String[] { "https://taskcluster.net", "https://taskcluster.net/" };
15-
16-
private final static String[] newRootURLs = new String[] { "https://taskcluster.example.com",
17-
"https://taskcluster.example.com/" };
18-
1915
/**
2016
* greenTick is an ANSI byte sequence to render a light green tick in a
2117
* color console.
2218
*/
23-
private final static byte[] greenTick = new byte[] { 0x1b, 0x5b, 0x33, 0x32, 0x6d, (byte) 0xe2, (byte) 0x9c,
19+
private final static byte[] greenTick = new byte[] { 0x1b, 0x5b, 0x33, 0x32, 0x6d, (byte) 0xe2, (byte) 0x9c,
2420
(byte) 0x93, 0x1b, 0x5b, 0x30, 0x6d };
2521

2622
/**
2723
* testURLs iterates through the language-agnostic test cases defined in
28-
* /specification.yml to ensure that the java implementation returns
29-
* consistent results with the other language implementations.
24+
* /tests.yml to ensure that the java implementation returns consistent
25+
* results with the other language implementations.
3026
*/
3127
@Test
3228
public void testURLs() throws Exception {
33-
Yaml yaml = new Yaml(new Constructor(TestCases.class));
34-
InputStream inputStream = this.getClass().getClassLoader().getResourceAsStream("specification.yml");
35-
TestCases testCases = yaml.load(inputStream);
36-
for (TestCase testCase : testCases.getSpecs()) {
37-
for (String[] argSet : testCase.getArgSets()) {
38-
String methodName = testCase.getType();
39-
40-
String oldExpectedUrl = testCase.getOldExpectedUrl();
41-
for (String rootURL : oldRootURLs) {
42-
this.test(oldExpectedUrl, rootURL, methodName, argSet);
43-
}
44-
45-
String newExpectedUrl = testCase.getExpectedUrl();
46-
for (String rootURL : newRootURLs) {
47-
this.test(newExpectedUrl, rootURL, methodName, argSet);
29+
Yaml yaml = new Yaml(new Constructor(TestsSpecification.class));
30+
InputStream inputStream = this.getClass().getClassLoader().getResourceAsStream("tests.yml");
31+
TestsSpecification spec = yaml.load(inputStream);
32+
for (TestCase test : spec.getTests()) {
33+
for (String[] argSet : test.getArgSets()) {
34+
for (String cluster : spec.getRootURLs().keySet()) {
35+
for (String rootURL : spec.getRootURLs().get(cluster)) {
36+
this.test(test.getExpected().get(cluster), rootURL, test.getFunction(), argSet);
37+
}
4838
}
4939
}
5040
}
@@ -57,9 +47,9 @@ private static void test(String expectedUrl, String rootURL, String methodName,
5747
System.out.println(" " + methodName + "(" + quotedList(rootURL, argSet) + ") = " + expectedUrl);
5848
}
5949

60-
public static String testFunc(String functionType, URLProvider urlProvider, String[] args)
50+
public static String testFunc(String function, URLProvider urlProvider, String[] args)
6151
throws NoSuchMethodException {
62-
switch (functionType) {
52+
switch (function) {
6353
case "api":
6454
return urlProvider.api(args[0], args[1], args[2]);
6555
case "apiReference":
@@ -75,7 +65,7 @@ public static String testFunc(String functionType, URLProvider urlProvider, Stri
7565
case "servicesManifest":
7666
return urlProvider.servicesManifest();
7767
default:
78-
throw new NoSuchMethodException("Unknown function type: " + functionType);
68+
throw new NoSuchMethodException("Unknown function type: " + function);
7969
}
8070
}
8171

tcurls_test.go

Lines changed: 38 additions & 62 deletions
Original file line numberDiff line numberDiff line change
@@ -1,110 +1,86 @@
11
package tcurls
22

33
import (
4-
"fmt"
54
"io/ioutil"
65
"strings"
76
"testing"
87

98
"gopkg.in/yaml.v2"
109
)
1110

12-
const rootURL = "https://taskcluster.example.com"
13-
14-
type spec struct {
15-
FunctionType string `yaml:"type"`
16-
ExpectedURL string `yaml:"expectedUrl"`
17-
OldExpectedURL string `yaml:"oldExpectedUrl"`
18-
ArgSets [][]string `yaml:"argSets"`
11+
type TestCase struct {
12+
Function string `yaml:"function"`
13+
Expected map[string]string `yaml:"expected"`
14+
ArgSets [][]string `yaml:"argSets"`
1915
}
2016

21-
type document struct {
22-
Specs []spec `yaml:"specs"`
17+
type TestsSpecification struct {
18+
RootURLs map[string][]string `yaml:"rootURLs"`
19+
Tests []TestCase `yaml:"tests"`
2320
}
2421

25-
func testFunc(t *testing.T, functionType string, root string, args ...string) (string, error) {
26-
switch functionType {
22+
func testFunc(t *testing.T, function string, expectedURL string, root string, args ...string) {
23+
var actualURL string
24+
switch function {
2725
case "api":
28-
return API(root, args[0], args[1], args[2]), nil
26+
actualURL = API(root, args[0], args[1], args[2])
2927
case "apiReference":
30-
return APIReference(root, args[0], args[1]), nil
28+
actualURL = APIReference(root, args[0], args[1])
3129
case "docs":
32-
return Docs(root, args[0]), nil
30+
actualURL = Docs(root, args[0])
3331
case "exchangeReference":
34-
return ExchangeReference(root, args[0], args[1]), nil
32+
actualURL = ExchangeReference(root, args[0], args[1])
3533
case "schema":
36-
return Schema(root, args[0], args[1]), nil
34+
actualURL = Schema(root, args[0], args[1])
3735
case "ui":
38-
return UI(root, args[0]), nil
36+
actualURL = UI(root, args[0])
3937
case "servicesManifest":
40-
return ServicesManifest(root), nil
38+
actualURL = ServicesManifest(root)
4139
default:
42-
return "", fmt.Errorf("Unknown function type: %s", functionType)
40+
t.Errorf("Unknown function type: %s", function)
41+
return
42+
}
43+
if expectedURL != actualURL {
44+
t.Errorf("%v %v(%v) = `%v` but should be `%v`", redCross(), function, quotedList(root, args), actualURL, expectedURL)
45+
return
4346
}
47+
t.Logf("%v %v(%v) = `%v`", greenTick(), function, quotedList(root, args), actualURL)
4448
}
4549

4650
func TestURLs(t *testing.T) {
47-
data, err := ioutil.ReadFile("specification.yml")
51+
data, err := ioutil.ReadFile("tests.yml")
4852
if err != nil {
4953
t.Error(err)
5054
}
51-
var specs document
52-
err = yaml.Unmarshal([]byte(data), &specs)
55+
var spec TestsSpecification
56+
err = yaml.Unmarshal([]byte(data), &spec)
5357
if err != nil {
5458
t.Error(err)
5559
}
5660

57-
for _, test := range specs.Specs {
61+
for _, test := range spec.Tests {
5862
for _, argSet := range test.ArgSets {
59-
60-
// Test "new" URLs
61-
result, err := testFunc(t, test.FunctionType, rootURL, argSet...)
62-
if err != nil {
63-
t.Error(err)
64-
continue
65-
}
66-
if result != test.ExpectedURL {
67-
t.Errorf("URL is not correct. Got %q wanted %q", result, test.ExpectedURL)
68-
continue
63+
for cluster, rootURLs := range spec.RootURLs {
64+
for _, rootURL := range rootURLs {
65+
testFunc(t, test.Function, test.Expected[cluster], rootURL, argSet...)
66+
}
6967
}
70-
result, err = testFunc(t, test.FunctionType, fmt.Sprintf("%s/", rootURL), argSet...)
71-
if err != nil {
72-
t.Error(err)
73-
}
74-
if result != test.ExpectedURL {
75-
t.Errorf("URL is not correct. Got %q wanted %q", result, test.ExpectedURL)
76-
continue
77-
}
78-
t.Logf(`%v %v(%v) = %q`, greenTick(), test.FunctionType, quotedList(rootURL, argSet), result)
79-
80-
// Test "old" URLs
81-
result, err = testFunc(t, test.FunctionType, oldRootURL, argSet...)
82-
if err != nil {
83-
t.Error(err)
84-
}
85-
if result != test.OldExpectedURL {
86-
t.Errorf("URL is not correct. Got %q wanted %q", result, test.OldExpectedURL)
87-
}
88-
result, err = testFunc(t, test.FunctionType, fmt.Sprintf("%s/", oldRootURL), argSet...)
89-
if err != nil {
90-
t.Error(err)
91-
}
92-
if result != test.OldExpectedURL {
93-
t.Errorf("URL is not correct. Got %q wanted %q", result, test.OldExpectedURL)
94-
}
95-
t.Logf(`%v %v(%v) = %q`, greenTick(), test.FunctionType, quotedList(oldRootURL, argSet), result)
9668
}
9769
}
9870
}
9971

100-
// quotedList returns a quoted list of the arguments passed in
72+
// quotedList returns a backtick-quoted list of the arguments passed in
10173
func quotedList(url string, args []string) string {
10274
all := append([]string{url}, args...)
103-
return `'` + strings.Join(all, `', '`) + `'`
75+
return "`" + strings.Join(all, "`, `") + "`"
10476
}
10577

10678
// greenTick returns an ANSI string including escape codes to render a light
10779
// green tick (✓) in a color console
10880
func greenTick() string {
10981
return string([]byte{0x1b, 0x5b, 0x33, 0x32, 0x6d, 0xe2, 0x9c, 0x93, 0x1b, 0x5b, 0x30, 0x6d})
11082
}
83+
84+
func redCross() string {
85+
return "❌"
86+
}

0 commit comments

Comments
 (0)