github.com/grailbio/base@v0.0.11/digest/digest_test.go (about) 1 // Copyright 2017 GRAIL, Inc. All rights reserved. 2 // Use of this source code is governed by the Apache 2.0 3 // license that can be found in the LICENSE file. 4 5 package digest 6 7 import ( 8 "bytes" 9 "crypto" 10 _ "crypto/md5" 11 _ "crypto/sha1" 12 _ "crypto/sha256" 13 _ "crypto/sha512" 14 "encoding/gob" 15 "encoding/json" 16 "testing" 17 18 _ "golang.org/x/crypto/blake2b" 19 _ "golang.org/x/crypto/md4" 20 _ "golang.org/x/crypto/ripemd160" 21 _ "golang.org/x/crypto/sha3" 22 ) 23 24 func TestDigest(t *testing.T) { 25 for _, tc := range []struct { 26 fn crypto.Hash 27 name string 28 out string 29 }{ 30 {crypto.SHA256, `"sha256"`, "sha256:68e656b251e67e8358bef8483ab0d51c6619f3e7a1a9f0e75838d41ff368f728"}, 31 {crypto.MD5, `"md5"`, "md5:3adbbad1791fbae3ec908894c4963870"}, 32 {crypto.SHA512, `"sha512"`, "sha512:6c2618358da07c830b88c5af8c3535080e8e603c88b891028a259ccdb9ac802d0fc0170c99d58affcf00786ce188fc5d753e8c6628af2071c3270d50445c4b1c"}, 33 } { 34 dig := Digester(tc.fn) 35 d := dig.FromString("hello, world!") 36 if got, want := d.String(), tc.out; got != want { 37 t.Fatalf("got %v want %v", got, want) 38 } 39 dd, err := dig.Parse(tc.out) 40 if err != nil { 41 t.Fatalf("parse failed: %v", err) 42 } 43 if got, want := dd, d; got != want { 44 t.Fatalf("got %v want %v", got, want) 45 } 46 dd, err = dig.Parse(tc.out[len(tc.name)-1:]) 47 if err != nil { 48 t.Fatalf("parse failed: %v", err) 49 } 50 if got, want := dd, d; got != want { 51 t.Fatalf("got %v want %v", got, want) 52 } 53 if got, want := dd.Hash(), tc.fn; got != want { 54 t.Fatalf("got %v want %v", got, want) 55 } 56 } 57 } 58 59 func TestReadWrite(t *testing.T) { 60 for _, k := range []crypto.Hash{ 61 crypto.MD4, 62 crypto.MD5, 63 crypto.SHA1, 64 crypto.SHA256, 65 crypto.SHA512, 66 crypto.SHA3_256, 67 crypto.SHA3_512, 68 crypto.SHA512_256, 69 crypto.BLAKE2b_256, 70 crypto.BLAKE2b_384, 71 crypto.BLAKE2b_512, 72 } { 73 dig := Digester(k) 74 d := dig.FromString("hello, world!") 75 var b bytes.Buffer 76 if _, err := WriteDigest(&b, d); err != nil { 77 t.Fatal(err) 78 } 79 dd, err := ReadDigest(&b) 80 if err != nil { 81 t.Fatal(err) 82 } 83 if got, want := dd, d; got != want { 84 t.Fatalf("got %v want %v", got, want) 85 } 86 } 87 // Test unknown digestHash 88 d := Digest{} 89 d.h = ^crypto.Hash(0) // make it nonzero but invalid so we don't hit the zero hash panic 90 var b bytes.Buffer 91 _, err := WriteDigest(&b, d) 92 if err == nil { 93 t.Fatalf("writing unknown digestHash should have failed") 94 } 95 } 96 97 func TestJSON(t *testing.T) { 98 for _, tc := range []struct { 99 fn crypto.Hash 100 name string 101 }{ 102 {crypto.SHA256, `"sha256"`}, 103 {crypto.MD5, `"md5"`}, 104 {crypto.SHA512, `"sha512"`}, 105 } { 106 d := Digester(tc.fn) 107 108 buffer := new(bytes.Buffer) 109 encoder := json.NewEncoder(buffer) 110 if err := encoder.Encode(d); err != nil { 111 t.Fatalf("Encoding failed: %v", err.Error()) 112 } 113 if got, want := buffer.String(), tc.name; got[:len(tc.name)] != want { 114 t.Fatalf("got %v want %v", got, want) 115 } 116 117 dec := Digester(0) 118 decoder := json.NewDecoder(buffer) 119 if err := decoder.Decode(&dec); err != nil { 120 t.Fatalf("decoded garbage to %v %v", buffer.String(), dec) 121 } 122 123 if dec != d { 124 t.Fatalf("got %v want %v", dec, d) 125 } 126 127 badD := Digester(0) 128 encoder = json.NewEncoder(buffer) 129 if err := encoder.Encode(badD); err == nil { 130 t.Fatalf("Encoding succeeded: %v %v", badD, buffer.String()) 131 } 132 133 badBuffer := bytes.NewBufferString("garbage") 134 decoder = json.NewDecoder(badBuffer) 135 if err := decoder.Decode(&dec); err == nil { 136 t.Fatalf("decoded garbage to %v %v", buffer.String(), dec) 137 } 138 } 139 } 140 141 func TestAbbrev(t *testing.T) { 142 d := Digester(crypto.SHA256) 143 for _, tc := range []struct { 144 id string 145 abbrev bool 146 }{ 147 {"9909853c8cada5431400c5f89fe5658e139aea88cab8c1479a8c35c902b1cb49", false}, 148 {"9909853c8cada5431400c5f89fe5658e139aea88cab8c1479a8c000000000000", false}, 149 {"9909853c8cada5431400c5f89fe5658e139a0000000000000000000000000000", false}, 150 {"9909853c8cada5431400c5f89fe0", true}, 151 {"9909853c8cada5", true}, 152 } { 153 id, err := d.Parse(tc.id) 154 if err != nil { 155 t.Errorf("parse %v: %v", tc.id, err) 156 continue 157 } 158 if got, want := id.IsAbbrev(), tc.abbrev; got != want { 159 t.Errorf("%v: got %v, want %v", id, got, want) 160 } 161 } 162 } 163 164 func TestTruncate(t *testing.T) { 165 d := Digester(crypto.SHA256) 166 id, err := d.Parse("9909853c8cada5431400c5f89fe5658e139aea88cab8c1479a8c35c902b1cb49") 167 if err != nil { 168 t.Fatal(err) 169 } 170 id.Truncate(4) 171 if got, want := id.IsAbbrev(), true; got != want { 172 t.Errorf("got %v, want %v", got, want) 173 } 174 if got, want := id.IsShort(), true; got != want { 175 t.Errorf("got %v, want %v", got, want) 176 } 177 if got, want := id.String(), "sha256:9909853c00000000000000000000000000000000000000000000000000000000"; got != want { 178 t.Errorf("got %v, want %v", got, want) 179 } 180 if got, want := id.HexN(4), "9909853c"; got != want { 181 t.Errorf("got %v, want %v", got, want) 182 } 183 } 184 185 func TestNPrefix(t *testing.T) { 186 d := Digester(crypto.SHA256) 187 id, err := d.Parse("9909853c8cada54314ddc5f89fe5658e139aea88cab8c1479a8c35c902b1cb49") 188 if err != nil { 189 t.Fatal(err) 190 } 191 for n := 32; n >= 0; n-- { 192 id.Truncate(n) 193 if got, want := id.NPrefix(), n; got != want { 194 t.Errorf("got %v, want %v for %v", got, want, id) 195 } 196 } 197 } 198 199 func TestGob(t *testing.T) { 200 id, err := Parse("sha256:9909853c8cada5431400c5f89fe5658e139aea88cab8c1479a8c35c902b1cb49") 201 if err != nil { 202 t.Fatal(err) 203 } 204 var b bytes.Buffer 205 enc := gob.NewEncoder(&b) 206 if err := enc.Encode(id); err != nil { 207 t.Fatal(err) 208 } 209 dec := gob.NewDecoder(&b) 210 var id2 Digest 211 if err := dec.Decode(&id2); err != nil { 212 t.Fatal(err) 213 } 214 if got, want := id2, id; got != want { 215 t.Errorf("got %v, want %v", got, want) 216 } 217 } 218 219 func TestParse(t *testing.T) { 220 for _, hash := range []string{"", "<zero>"} { 221 h, err := Parse(hash) 222 if err != nil { 223 t.Fatal(err) 224 } 225 if got, want := h, (Digest{}); got != want { 226 t.Errorf("got %v, want %v", got, want) 227 } 228 } 229 }