Skip to content

Commit

Permalink
Merge pull request cosmos#56 from ChorusOne/giulio/go_unit_test
Browse files Browse the repository at this point in the history
Refactoring go test cases to be in json format
  • Loading branch information
ethanfrey authored Nov 23, 2021
2 parents dc210c0 + 552c01c commit 42d3932
Show file tree
Hide file tree
Showing 14 changed files with 1,140 additions and 830 deletions.
5 changes: 0 additions & 5 deletions go.mod

This file was deleted.

16 changes: 0 additions & 16 deletions go.sum

This file was deleted.

79 changes: 79 additions & 0 deletions go/ops_data_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
package ics23

import (
"encoding/hex"
"encoding/json"
"os"
"path/filepath"
"testing"
)

type LeafOpTestStruct struct {
Op *LeafOp
Key []byte
Value []byte
IsErr bool
Expected []byte
}

func LeafOpTestData(t *testing.T) map[string]LeafOpTestStruct {
fname := filepath.Join("..", "testdata", "TestLeafOpData.json")
ffile, err := os.Open(fname)
if err != nil {
t.Fatal(err)
}
var cases map[string]LeafOpTestStruct
jsonDecoder := json.NewDecoder(ffile)
err = jsonDecoder.Decode(&cases)
if err != nil {
t.Fatal(err)
}
return cases
}

type InnerOpTestStruct struct {
Op *InnerOp
Child []byte
IsErr bool
Expected []byte
}

func InnerOpTestData(t *testing.T) map[string]InnerOpTestStruct {
fname := filepath.Join("..", "testdata", "TestInnerOpData.json")
ffile, err := os.Open(fname)
if err != nil {
t.Fatal(err)
}
var cases map[string]InnerOpTestStruct
jsonDecoder := json.NewDecoder(ffile)
err = jsonDecoder.Decode(&cases)
if err != nil {
t.Fatal(err)
}
return cases
}

type DoHashTestStruct struct {
HashOp HashOp
Preimage string
ExpectedHash string
}

func DoHashTestData(t *testing.T) map[string]DoHashTestStruct {
fname := filepath.Join("..", "testdata", "TestDoHashData.json")
ffile, err := os.Open(fname)
if err != nil {
t.Fatal(err)
}
var cases map[string]DoHashTestStruct
jsonDecoder := json.NewDecoder(ffile)
err = jsonDecoder.Decode(&cases)
if err != nil {
t.Fatal(err)
}
return cases
}

func toHex(data []byte) string {
return hex.EncodeToString(data)
}
220 changes: 18 additions & 202 deletions go/ops_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,241 +7,57 @@ import (
)

func TestLeafOp(t *testing.T) {
cases := map[string]struct {
op *LeafOp
key []byte
value []byte
isErr bool
expected []byte
}{
"hash foobar": {
op: &LeafOp{
Hash: HashOp_SHA256,
// no prehash, no length prefix
},
key: []byte("foo"),
value: []byte("bar"),
// echo -n foobar | sha256sum
expected: fromHex("c3ab8ff13720e8ad9047dd39466b3c8974e592c2fa383d4a3960714caef0c4f2"),
},
"hash foobaz, sha-512": {
op: &LeafOp{
Hash: HashOp_SHA512,
// no prehash, no length prefix
},
key: []byte("foo"),
value: []byte("baz"),
// echo -n foobaz | sha512sum
expected: fromHex("4f79f191298ec7461d60136c60f77c2ae8ddd85dbf6168bb925092d51bfb39b559219b39ae5385ba04946c87f64741385bef90578ea6fe6dac85dbf7ad3f79e1"),
},
"hash foobar (different break)": {
op: &LeafOp{
Hash: HashOp_SHA256,
// no prehash, no length prefix
},
key: []byte("f"),
value: []byte("oobar"),
// echo -n foobar | sha256sum
expected: fromHex("c3ab8ff13720e8ad9047dd39466b3c8974e592c2fa383d4a3960714caef0c4f2"),
},
"requires key": {
op: &LeafOp{
Hash: HashOp_SHA256,
// no prehash, no length prefix
},
key: []byte("foo"),
isErr: true,
},
"requires value": {
op: &LeafOp{
Hash: HashOp_SHA256,
// no prehash, no length prefix
},
value: []byte("bar"),
isErr: true,
},
"hash with length prefix": {
op: &LeafOp{
Hash: HashOp_SHA256,
Length: LengthOp_VAR_PROTO,
// no prehash
},
// echo -n food | xxs -ps
// and manually compute length byte
key: []byte("food"), // 04666f6f64
value: []byte("some longer text"), // 10736f6d65206c6f6e6765722074657874
// echo -n 04666f6f6410736f6d65206c6f6e6765722074657874 | xxd -r -p | sha256sum
expected: fromHex("b68f5d298e915ae1753dd333da1f9cf605411a5f2e12516be6758f365e6db265"),
},
"hash with prehash and length prefix": {
op: &LeafOp{
Hash: HashOp_SHA256,
Length: LengthOp_VAR_PROTO,
PrehashValue: HashOp_SHA256,
},
key: []byte("food"), // 04666f6f64
// TODO: this is hash, then length....
// echo -n yet another long string | sha256sum
value: []byte("yet another long string"), // 20a48c2d4f67b9f80374938535285ed285819d8a5a8fc1fccd1e3244e437cf290d
// echo -n 04666f6f6420a48c2d4f67b9f80374938535285ed285819d8a5a8fc1fccd1e3244e437cf290d | xxd -r -p | sha256sum
expected: fromHex("87e0483e8fb624aef2e2f7b13f4166cda485baa8e39f437c83d74c94bedb148f"),
},
"hash with length prefix (fixed 32-bit little-endian encoding)": {
op: &LeafOp{
Hash: HashOp_SHA256,
Length: LengthOp_FIXED32_LITTLE,
// no prehash
},
// echo -n food | xxs -ps
// and manually compute length bytes
key: []byte("food"), // 04000000666f6f64
value: []byte("some longer text"), // 10000000736f6d65206c6f6e6765722074657874
// echo -n 04000000666f6f6410000000736f6d65206c6f6e6765722074657874 | xxd -r -p | sha256sum
expected: fromHex("c853652437be02501c674744bf2a2b45d92a0a9f29c4b1044010fb3e2d43a949"),
},
}
cases := LeafOpTestData(t)

for name, tc := range cases {
t.Run(name, func(t *testing.T) {
res, err := tc.op.Apply(tc.key, tc.value)
res, err := tc.Op.Apply(tc.Key, tc.Value)
// short-circuit with error case
if tc.isErr {
if err == nil {
t.Fatal("Expected error, but got none")
}
return
if tc.IsErr && err == nil {
t.Fatal("Expected error, but got none")
}

if err != nil {
if tc.IsErr == false && err != nil {
t.Fatal(err)
}
if !bytes.Equal(res, tc.expected) {
t.Errorf("Bad result: %s vs %s", toHex(res), toHex(tc.expected))
if !bytes.Equal(res, tc.Expected) {
t.Errorf("Bad result: %s vs %s", toHex(res), toHex(tc.Expected))
}
})
}
}

func TestInnerOp(t *testing.T) {
cases := map[string]struct {
op *InnerOp
child []byte
isErr bool
expected []byte
}{
"requires child": {
op: &InnerOp{
Hash: HashOp_SHA256,
Prefix: fromHex("0123456789"),
Suffix: fromHex("deadbeef"),
},
isErr: true,
},
"hash child with prefix and suffix": {
op: &InnerOp{
Hash: HashOp_SHA256,
Prefix: fromHex("0123456789"),
Suffix: fromHex("deadbeef"),
},
child: fromHex("00cafe00"),
// echo -n 012345678900cafe00deadbeef | xxd -r -p | sha256sum
expected: fromHex("0339f76086684506a6d42a60da4b5a719febd4d96d8b8d85ae92849e3a849a5e"),
},
"hash child with only prefix": {
op: &InnerOp{
Hash: HashOp_SHA256,
Prefix: fromHex("00204080a0c0e0"),
},
child: fromHex("ffccbb997755331100"),
// echo -n 00204080a0c0e0ffccbb997755331100 | xxd -r -p | sha256sum
expected: fromHex("45bece1678cf2e9f4f2ae033e546fc35a2081b2415edcb13121a0e908dca1927"),
},
"hash child with only suffix": {
op: &InnerOp{
Hash: HashOp_SHA256,
Suffix: []byte(" just kidding!"),
},
child: []byte("this is a sha256 hash, really...."),
// echo -n 'this is a sha256 hash, really.... just kidding!' | sha256sum
expected: fromHex("79ef671d27e42a53fba2201c1bbc529a099af578ee8a38df140795db0ae2184b"),
},
}
cases := InnerOpTestData(t)

for name, tc := range cases {
t.Run(name, func(t *testing.T) {
res, err := tc.op.Apply(tc.child)
// short-circuit with error case
if tc.isErr {
if err == nil {
t.Fatal("Expected error, but got none")
}
return
res, err := tc.Op.Apply(tc.Child)
if tc.IsErr && err == nil {
t.Fatal("Expected error, but got none")
}

if err != nil {
if tc.IsErr == false && err != nil {
t.Fatal(err)
}
if !bytes.Equal(res, tc.expected) {
t.Errorf("Bad result: %s vs %s", toHex(res), toHex(tc.expected))
if !bytes.Equal(res, tc.Expected) {
t.Errorf("Bad result: %s vs %s", toHex(res), toHex(tc.Expected))
}
})
}
}

func TestDoHash(t *testing.T) {
cases := map[string]struct {
hashOp HashOp
preimage string
expectedHash string
}{
"sha256": {
hashOp: HashOp_SHA256,
preimage: "food",
// echo -n food | sha256sum
expectedHash: "c1f026582fe6e8cb620d0c85a72fe421ddded756662a8ec00ed4c297ad10676b",
},
"ripemd160": {
hashOp: HashOp_RIPEMD160,
preimage: "food",
// echo -n food | openssl dgst -rmd160 -hex | cut -d' ' -f2
expectedHash: "b1ab9988c7c7c5ec4b2b291adfeeee10e77cdd46",
},
"bitcoin": {
hashOp: HashOp_BITCOIN,
preimage: "food",
// echo -n c1f026582fe6e8cb620d0c85a72fe421ddded756662a8ec00ed4c297ad10676b | xxd -r -p | openssl dgst -rmd160 -hex
expectedHash: "0bcb587dfb4fc10b36d57f2bba1878f139b75d24",
},
"sha512_256": {
hashOp: HashOp_SHA512_256,
preimage: "food",
// echo -n food | openssl dgst -sha512-256 -hex | cut -d' ' -f2
expectedHash: "5b3a452a6acbf1fc1e553a40c501585d5bd3cca176d562e0a0e19a3c43804e88",
},
}
cases := DoHashTestData(t)

for name, tc := range cases {
t.Run(name, func(t *testing.T) {
res, err := doHash(tc.hashOp, []byte(tc.preimage))
res, err := doHash(tc.HashOp, []byte(tc.Preimage))
if err != nil {
t.Fatal(err)
}
hexRes := hex.EncodeToString(res)
if hexRes != tc.expectedHash {
t.Fatalf("Expected %s got %s", tc.expectedHash, hexRes)
if hexRes != tc.ExpectedHash {
t.Fatalf("Expected %s got %s", tc.ExpectedHash, hexRes)
}
})
}
}

func fromHex(data string) []byte {
res, err := hex.DecodeString(data)
if err != nil {
panic(err)
}
return res
}

func toHex(data []byte) string {
return hex.EncodeToString(data)
}
Loading

0 comments on commit 42d3932

Please sign in to comment.