10472: Handle jobs with components/subjobs
[arvados.git] / sdk / go / blockdigest / blockdigest_test.go
1 package blockdigest
2
3 import (
4         "fmt"
5         "runtime"
6         "strings"
7         "testing"
8 )
9
10 func getStackTrace() string {
11         buf := make([]byte, 1000)
12         bytes_written := runtime.Stack(buf, false)
13         return "Stack Trace:\n" + string(buf[:bytes_written])
14 }
15
16 func expectEqual(t *testing.T, actual interface{}, expected interface{}) {
17         if actual != expected {
18                 t.Fatalf("Expected %v but received %v instead. %s",
19                         expected,
20                         actual,
21                         getStackTrace())
22         }
23 }
24
25 func expectStringSlicesEqual(t *testing.T, actual []string, expected []string) {
26         if len(actual) != len(expected) {
27                 t.Fatalf("Expected %v (length %d), but received %v (length %d) instead. %s", expected, len(expected), actual, len(actual), getStackTrace())
28         }
29         for i := range actual {
30                 if actual[i] != expected[i] {
31                         t.Fatalf("Expected %v but received %v instead (first disagreement at position %d). %s", expected, actual, i, getStackTrace())
32                 }
33         }
34 }
35
36 func expectValidDigestString(t *testing.T, s string) {
37         bd, err := FromString(s)
38         if err != nil {
39                 t.Fatalf("Expected %s to produce a valid BlockDigest but instead got error: %v", s, err)
40         }
41
42         expected := strings.ToLower(s)
43
44         if expected != bd.String() {
45                 t.Fatalf("Expected %s to be returned by FromString(%s).String() but instead we received %s", expected, s, bd.String())
46         }
47 }
48
49 func expectInvalidDigestString(t *testing.T, s string) {
50         _, err := FromString(s)
51         if err == nil {
52                 t.Fatalf("Expected %s to be an invalid BlockDigest, but did not receive an error", s)
53         }
54 }
55
56 func expectBlockLocator(t *testing.T, actual BlockLocator, expected BlockLocator) {
57         expectEqual(t, actual.Digest, expected.Digest)
58         expectEqual(t, actual.Size, expected.Size)
59         expectStringSlicesEqual(t, actual.Hints, expected.Hints)
60 }
61
62 func expectLocatorPatternMatch(t *testing.T, s string) {
63         if !LocatorPattern.MatchString(s) {
64                 t.Fatalf("Expected \"%s\" to match locator pattern but it did not.",
65                         s)
66         }
67 }
68
69 func expectLocatorPatternFail(t *testing.T, s string) {
70         if LocatorPattern.MatchString(s) {
71                 t.Fatalf("Expected \"%s\" to fail locator pattern but it passed.",
72                         s)
73         }
74 }
75
76 func TestValidDigestStrings(t *testing.T) {
77         expectValidDigestString(t, "01234567890123456789abcdefabcdef")
78         expectValidDigestString(t, "01234567890123456789ABCDEFABCDEF")
79         expectValidDigestString(t, "01234567890123456789AbCdEfaBcDeF")
80 }
81
82 func TestInvalidDigestStrings(t *testing.T) {
83         expectInvalidDigestString(t, "01234567890123456789abcdefabcdeg")
84         expectInvalidDigestString(t, "01234567890123456789abcdefabcde")
85         expectInvalidDigestString(t, "01234567890123456789abcdefabcdefa")
86         expectInvalidDigestString(t, "g1234567890123456789abcdefabcdef")
87 }
88
89 func TestBlockDigestWorksAsMapKey(t *testing.T) {
90         m := make(map[BlockDigest]int)
91         bd, err := FromString("01234567890123456789abcdefabcdef")
92         if err != nil {
93                 t.Fatalf("Unexpected error during FromString for block: %v", err)
94         }
95         m[bd] = 5
96 }
97
98 func TestBlockDigestGetsPrettyPrintedByPrintf(t *testing.T) {
99         input := "01234567890123456789abcdefabcdef"
100         fromString, err := FromString(input)
101         if err != nil {
102                 t.Fatalf("Unexpected error during FromString: %v", err)
103         }
104         prettyPrinted := fmt.Sprintf("%v", fromString)
105         if prettyPrinted != input {
106                 t.Fatalf("Expected blockDigest produced from \"%s\" to be printed as "+
107                         "\"%s\", but instead it was printed as %s",
108                         input, input, prettyPrinted)
109         }
110 }
111
112 func TestBlockDigestGetsPrettyPrintedByPrintfInNestedStructs(t *testing.T) {
113         input, err := FromString("01234567890123456789abcdefabcdef")
114         if err != nil {
115                 t.Fatalf("Unexpected error during FromString for block: %v", err)
116         }
117         value := 42
118         nested := struct {
119                 // Fun trivia fact: If this field was called "digest" instead of
120                 // "Digest", then it would not be exported and String() would
121                 // never get called on it and our output would look very
122                 // different.
123                 Digest BlockDigest
124                 value  int
125         }{
126                 input,
127                 value,
128         }
129         prettyPrinted := fmt.Sprintf("%+v", nested)
130         expected := fmt.Sprintf("{Digest:%s value:%d}", input, value)
131         if prettyPrinted != expected {
132                 t.Fatalf("Expected blockDigest produced from \"%s\" to be printed as "+
133                         "\"%s\", but instead it was printed as %s",
134                         input, expected, prettyPrinted)
135         }
136 }
137
138 func TestLocatorPatternBasic(t *testing.T) {
139         expectLocatorPatternMatch(t, "12345678901234567890123456789012+12345")
140         expectLocatorPatternMatch(t, "A2345678901234abcdefababdeffdfdf+12345")
141         expectLocatorPatternMatch(t, "12345678901234567890123456789012+12345+A1")
142         expectLocatorPatternMatch(t,
143                 "12345678901234567890123456789012+12345+A1+B123wxyz@_-")
144         expectLocatorPatternMatch(t,
145                 "12345678901234567890123456789012+12345+A1+B123wxyz@_-+C@")
146         expectLocatorPatternMatch(t, "12345678901234567890123456789012+12345+A")
147         expectLocatorPatternMatch(t, "12345678901234567890123456789012+12345+A1+B")
148         expectLocatorPatternMatch(t, "12345678901234567890123456789012+12345+A+B2")
149
150         expectLocatorPatternFail(t, "12345678901234567890123456789012")
151         expectLocatorPatternFail(t, "12345678901234567890123456789012+")
152         expectLocatorPatternFail(t, "12345678901234567890123456789012+12345+")
153         expectLocatorPatternFail(t, "1234567890123456789012345678901+12345")
154         expectLocatorPatternFail(t, "123456789012345678901234567890123+12345")
155         expectLocatorPatternFail(t, "g2345678901234abcdefababdeffdfdf+12345")
156         expectLocatorPatternFail(t, "12345678901234567890123456789012+12345 ")
157         expectLocatorPatternFail(t, "12345678901234567890123456789012+12345+1")
158         expectLocatorPatternFail(t, "12345678901234567890123456789012+12345+1A")
159         expectLocatorPatternFail(t, "12345678901234567890123456789012+12345+a1")
160         expectLocatorPatternFail(t, "12345678901234567890123456789012+12345+A1+")
161
162 }
163
164 func TestParseBlockLocatorSimple(t *testing.T) {
165         b, err := ParseBlockLocator("365f83f5f808896ec834c8b595288735+2310+K@qr1hi+Af0c9a66381f3b028677411926f0be1c6282fe67c@542b5ddf")
166         if err != nil {
167                 t.Fatalf("Unexpected error parsing block locator: %v", err)
168         }
169         d, err := FromString("365f83f5f808896ec834c8b595288735")
170         if err != nil {
171                 t.Fatalf("Unexpected error during FromString for block: %v", err)
172         }
173         expectBlockLocator(t, b, BlockLocator{Digest: d,
174                 Size: 2310,
175                 Hints: []string{"K@qr1hi",
176                         "Af0c9a66381f3b028677411926f0be1c6282fe67c@542b5ddf"}})
177 }