1// Copyright 2019 Google LLC 2// 3// Licensed under the Apache License, Version 2.0 (the "License"); 4// you may not use this file except in compliance with the License. 5// You may obtain a copy of the License at 6// 7// http://www.apache.org/licenses/LICENSE-2.0 8// 9// Unless required by applicable law or agreed to in writing, software 10// distributed under the License is distributed on an "AS IS" BASIS, 11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12// See the License for the specific language governing permissions and 13// limitations under the License. 14// 15//////////////////////////////////////////////////////////////////////////////// 16 17package testutil 18 19import ( 20 "encoding/hex" 21 "encoding/json" 22 "errors" 23 "os" 24 "path/filepath" 25 "testing" 26) 27 28const ( 29 wycheproofDir = "wycheproof/testvectors" 30) 31 32// SkipTestIfTestSrcDirIsNotSet skips the test if TEST_SRCDIR is not set. 33// This is necessary when not using Blaze/Bazel, as we don't have a solution for referencing non-Go 34// resources that are external to the repository with Go tooling. 35func SkipTestIfTestSrcDirIsNotSet(t *testing.T) { 36 t.Helper() 37 if _, ok := os.LookupEnv("TEST_SRCDIR"); !ok { 38 t.Skip("TEST_SRCDIR not found") 39 } 40} 41 42// WycheproofSuite represents the common elements of the top level 43// object in a Wycheproof json file. Implementations should embed 44// WycheproofSuite in a struct that strongly types the testGroups 45// field. See wycheproofutil_test.go for an example. 46type WycheproofSuite struct { 47 Algorithm string `json:"algorithm"` 48 GeneratorVersion string `json:"generatorVersion"` 49 NumberOfTests int `json:"numberOfTests"` 50 Notes map[string]string `json:"notes"` 51} 52 53// WycheproofGroup represents the common elements of a testGroups 54// object in a Wycheproof suite. Implementations should embed 55// WycheproofGroup in a struct that strongly types its list of cases. 56// See wycheproofutil_test.go for an example. 57type WycheproofGroup struct { 58 Type string `json:"type"` 59} 60 61// WycheproofCase represents the common elements of a tests object 62// in a Wycheproof group. Implementation should embed WycheproofCase 63// in a struct that contains fields specific to the test type. 64// See wycheproofutil_test.go for an example. 65type WycheproofCase struct { 66 CaseID int `json:"tcId"` 67 Comment string `json:"comment"` 68 Result string `json:"result"` 69 Flags []string `json:"flags"` 70} 71 72// HexBytes is a helper type for unmarshalling a byte sequence represented as a 73// hex encoded string. 74type HexBytes []byte 75 76// UnmarshalText converts a hex encoded string into a sequence of bytes. 77func (a *HexBytes) UnmarshalText(text []byte) error { 78 decoded, err := hex.DecodeString(string(text)) 79 if err != nil { 80 return err 81 } 82 83 *a = decoded 84 return nil 85} 86 87// PopulateSuite opens filename from the Wycheproof test vectors directory and 88// populates suite with the decoded JSON data. 89// 90// When using this in a test function, the function should start with 91// SkipTestIfTestSrcDirIsNotSet(), to expediently skip the test. 92func PopulateSuite(suite interface{}, filename string) error { 93 srcDir, ok := os.LookupEnv("TEST_SRCDIR") 94 if !ok { 95 return errors.New("TEST_SRCDIR not found") 96 } 97 f, err := os.Open(filepath.Join(srcDir, wycheproofDir, filename)) 98 if err != nil { 99 return err 100 } 101 parser := json.NewDecoder(f) 102 if err := parser.Decode(suite); err != nil { 103 return err 104 } 105 return nil 106} 107