github.com/bazelbuild/remote-apis-sdks@v0.0.0-20240425170053-8a36686a6350/go/pkg/digest/digest_test.go (about) 1 package digest 2 3 import ( 4 "fmt" 5 "os" 6 "path/filepath" 7 "strings" 8 "testing" 9 10 "google.golang.org/protobuf/proto" 11 ) 12 13 var ( 14 dInvalid = Digest{Hash: strings.Repeat("a", 25), Size: 321} 15 dSHA256 = Digest{Hash: strings.Repeat("a", 64), Size: 321} 16 dSHA256Sizeless = Digest{Hash: dSHA256.Hash, Size: -1} 17 18 sGood = fmt.Sprintf("%s/%d", dSHA256.Hash, dSHA256.Size) 19 sSizeless = fmt.Sprintf("%s/%d", dSHA256Sizeless.Hash, dSHA256Sizeless.Size) 20 sInvalid1 = fmt.Sprintf("%d/%s", dSHA256.Size, dSHA256.Hash) 21 sInvalid2 = fmt.Sprintf("%s/test", sInvalid1) 22 sInvalid3 = fmt.Sprintf("x%s", sGood[1:]) 23 ) 24 25 func TestProtoConversion(t *testing.T) { 26 dPb := dSHA256.ToProto() 27 d, err := NewFromProto(dPb) 28 if err != nil { 29 t.Errorf("NewFromProto(%v) = %v, want nil", dPb, err) 30 } 31 if dSHA256 != d { 32 t.Errorf("NewFromProto(%v.ToProto()) = (%s, _), want (%s, _)", dSHA256, d, dSHA256) 33 } 34 } 35 36 func TestValidateDigests_Pass(t *testing.T) { 37 if err := dSHA256.Validate(); err != nil { 38 t.Errorf("Validate(%v) = %v, want nil", dSHA256, err) 39 } 40 } 41 42 func TestValidateDigests_Errors(t *testing.T) { 43 t.Parallel() 44 testcases := []struct { 45 desc string 46 digest Digest 47 }{ 48 {"too short", Digest{Hash: "000a"}}, 49 {"too long", Digest{Hash: "0000000000000000000000000000000000000000000000000000000000000000a"}}, 50 {"must be lowercase", Digest{Hash: "000000000000000000000000000000000000000000000000000000000000000A"}}, 51 {"can't be crazy", Digest{Hash: "000000000000000000000000000000000000000000000000000000000foobar!"}}, 52 {"can't be negatively-sized", Digest{Hash: dSHA256.Hash, Size: -1}}, 53 } 54 for _, tc := range testcases { 55 err := tc.digest.Validate() 56 if err == nil { 57 t.Errorf("%s: got success, wanted error", tc.desc) 58 } 59 t.Logf("%s: correctly got an error (%s)", tc.desc, err) 60 } 61 } 62 63 func Test_New_Success(t *testing.T) { 64 t.Parallel() 65 gotDigest, err := New(dSHA256.Hash, dSHA256.Size) 66 if err != nil { 67 t.Errorf("New(%s, %d) = (_, %v), want (_, nil)", dSHA256.Hash, dSHA256.Size, err) 68 } 69 if dSHA256 != gotDigest { 70 t.Errorf("New(%s, %d) = (%v, _), want (%v, _)", dSHA256.Hash, dSHA256.Size, gotDigest, dSHA256) 71 } 72 } 73 74 func Test_New_Error(t *testing.T) { 75 t.Parallel() 76 gotDigest, err := New(dInvalid.Hash, dInvalid.Size) 77 if err == nil { 78 t.Errorf("New(%s, %d) = (%s, nil), want (_, error)", dInvalid.Hash, dInvalid.Size, gotDigest) 79 } 80 } 81 82 func Test_NewFromProto_Success(t *testing.T) { 83 t.Parallel() 84 dPb := dSHA256.ToProto() 85 gotDigest, err := NewFromProto(dPb) 86 if err != nil { 87 t.Errorf("NewFromProto(%v) = (_, %v), want (_, nil)", dPb, err) 88 } 89 if dSHA256 != gotDigest { 90 t.Errorf("NewFromProto(%v) = (%v, _), want (%v, _)", dPb, gotDigest, dSHA256) 91 } 92 } 93 94 func Test_NewFromProto_Error(t *testing.T) { 95 t.Parallel() 96 dPb := dInvalid.ToProto() 97 gotDigest, err := NewFromProto(dPb) 98 if err == nil { 99 t.Errorf("NewFromProto(%v) = (%s, nil), want (_, error)", gotDigest, dPb) 100 } 101 } 102 103 func TestNewFromProtoUnvalidated(t *testing.T) { 104 t.Parallel() 105 testcases := []struct { 106 label string 107 digest Digest 108 }{ 109 {"SHA256", dSHA256}, 110 {"Invalid", dInvalid}, 111 } 112 for _, tc := range testcases { 113 dPb := tc.digest.ToProto() 114 gotDigest := NewFromProtoUnvalidated(dPb) 115 if tc.digest != gotDigest { 116 t.Errorf("%s: NewFromProto(%v) = (%v, _), want (%v, _)", tc.label, dPb, gotDigest, tc.digest) 117 } 118 } 119 } 120 121 func TestTestNewPads(t *testing.T) { 122 t.Parallel() 123 dShort := TestNew("a", 0) 124 dFull := TestNew("000000000000000000000000000000000000000000000000000000000000000a", 0) 125 want := "000000000000000000000000000000000000000000000000000000000000000a" 126 if dShort.Hash != want { 127 t.Errorf("dShort.Hash = %s, want %s", dShort.Hash, want) 128 } 129 if dFull.Hash != want { 130 t.Errorf("dFull.Hash = %s, want %s", dFull.Hash, want) 131 } 132 } 133 134 func TestTestNew(t *testing.T) { 135 t.Parallel() 136 dWant := "000000000000000000000000000000000000000000000000000000000000000a" 137 if dGot := TestNew("a", 0); dGot.Hash != dWant { 138 t.Errorf("TestNew('a', _) = %v, want %v", dGot.Hash, dWant) 139 } 140 } 141 142 func TestTestNew_Panic(t *testing.T) { 143 t.Parallel() 144 d := &Digest{Hash: "not good", Size: -1} 145 defer func() { 146 if err := recover(); err == nil { 147 t.Errorf("TestNew(%v) should have panicked", d) 148 } 149 }() 150 TestNew(d.Hash, d.Size) 151 } 152 153 func TestNewFromBlob(t *testing.T) { 154 t.Parallel() 155 if dGot := NewFromBlob([]byte{}); dGot != Empty { 156 t.Errorf("NewFromBlob([]byte{}) = %v, want %v", dGot, Empty) 157 } 158 dWant := TestNew("039058c6f2c0cb492c533b0a4d14ef77cc0f78abccced5287d84a1a2011cfb81", 3) 159 if dGot := NewFromBlob([]byte{1, 2, 3}); dGot != dWant { 160 t.Errorf("NewFromBlob([]byte{}) = %v, want %v", dGot, dWant) 161 } 162 } 163 164 func Test_NewFromMessage(t *testing.T) { 165 t.Parallel() 166 // Use a repb.Digest as a black-box proto. 167 msg := NewFromBlob([]byte{1, 2, 3}).ToProto() 168 b, err := proto.Marshal(msg) 169 if err != nil { 170 t.Fatalf("proto.Marshal(%v) = (_, %v), want (_, nil)", msg, err) 171 } 172 dWant := NewFromBlob(b) 173 174 dGot, err := NewFromMessage(msg) 175 if err != nil { 176 t.Errorf("NewFromMessage(%v) = (_, %v), want (_, nil)", msg, err) 177 } 178 if dGot != dWant { 179 t.Errorf("NewFromMessage(%v) = (%v, _), want (%v, _)", msg, dGot, dWant) 180 } 181 } 182 183 func TestTestNewFromMessage(t *testing.T) { 184 t.Parallel() 185 // Use a repb.Digest as a black-box proto. 186 msg := NewFromBlob([]byte{1, 2, 3}).ToProto() 187 b, err := proto.Marshal(msg) 188 if err != nil { 189 t.Fatalf("proto.Marshal(%v) = (_, %v), want (_, nil)", msg, err) 190 } 191 dWant := NewFromBlob(b) 192 193 dGot := TestNewFromMessage(msg) 194 if dGot != dWant { 195 t.Errorf("TestNewFromMessage(%v) = (%v, _), want (%v, _)", msg, dGot, dWant) 196 } 197 } 198 199 func TestNewFromFile(t *testing.T) { 200 t.Parallel() 201 testDir := t.TempDir() 202 path := filepath.Join(testDir, "input") 203 if err := os.WriteFile(path, []byte{1, 2, 3}, os.FileMode(0666)); err != nil { 204 t.Fatalf("os.WriteFile(%v, _, _) = %v, want nil", path, err) 205 } 206 dWant := TestNew("039058c6f2c0cb492c533b0a4d14ef77cc0f78abccced5287d84a1a2011cfb81", 3) 207 dGot, err := NewFromFile(path) 208 if err != nil { 209 t.Errorf("NewFromFile(%v) = (_, %v), want (_, nil)", path, err) 210 } 211 if dGot != dWant { 212 t.Errorf("NewFromFile(%v) = (%v, _), want (%v, _)", path, dGot, dWant) 213 } 214 } 215 216 func TestString(t *testing.T) { 217 t.Parallel() 218 if sGot := dSHA256.String(); sGot != sGood { 219 t.Errorf("%v.String() = '%s', want '%s'", dSHA256, sGot, sGood) 220 } 221 if sGot := dSHA256Sizeless.String(); sGot != sSizeless { 222 t.Errorf("%v.String() = '%s', want '%s'", dSHA256Sizeless, sGot, sSizeless) 223 } 224 } 225 226 func TestNewFromString(t *testing.T) { 227 t.Parallel() 228 if dGot, err := NewFromString(sGood); err != nil || dGot != dSHA256 { 229 t.Errorf("FromString(%s) = (%v, %v), want (%v, nil)", sGood, dGot, err, dSHA256) 230 } 231 if _, err := NewFromString(sSizeless); err == nil { 232 t.Errorf("FromString(%s) = (_, nil), want (_, error)", sSizeless) 233 } 234 if _, err := NewFromString(sInvalid1); err == nil { 235 t.Errorf("FromString(%s) = (_, nil), want (_, error)", sInvalid1) 236 } 237 if _, err := NewFromString(sInvalid2); err == nil { 238 t.Errorf("FromString(%s) = (_, nil), want (_, error)", sInvalid2) 239 } 240 if _, err := NewFromString(sInvalid3); err == nil { 241 t.Errorf("FromString(%s) = (_, nil), want (_, error)", sInvalid3) 242 } 243 }