commit
d46bc091c0
@ -0,0 +1,29 @@ |
||||
package bech32 |
||||
|
||||
import ( |
||||
"github.com/btcsuite/btcutil/bech32" |
||||
"github.com/pkg/errors" |
||||
) |
||||
|
||||
//ConvertAndEncode converts from a base64 encoded byte string to base32 encoded byte string and then to bech32
|
||||
func ConvertAndEncode(hrp string, data []byte) (string, error) { |
||||
converted, err := bech32.ConvertBits(data, 8, 5, true) |
||||
if err != nil { |
||||
return "", errors.Wrap(err, "encoding bech32 failed") |
||||
} |
||||
return bech32.Encode(hrp, converted) |
||||
|
||||
} |
||||
|
||||
//DecodeAndConvert decodes a bech32 encoded string and converts to base64 encoded bytes
|
||||
func DecodeAndConvert(bech string) (string, []byte, error) { |
||||
hrp, data, err := bech32.Decode(bech) |
||||
if err != nil { |
||||
return "", nil, errors.Wrap(err, "decoding bech32 failed") |
||||
} |
||||
converted, err := bech32.ConvertBits(data, 5, 8, false) |
||||
if err != nil { |
||||
return "", nil, errors.Wrap(err, "decoding bech32 failed") |
||||
} |
||||
return hrp, converted, nil |
||||
} |
@ -0,0 +1,31 @@ |
||||
package bech32_test |
||||
|
||||
import ( |
||||
"bytes" |
||||
"crypto/sha256" |
||||
"testing" |
||||
|
||||
"github.com/tendermint/tendermint/libs/bech32" |
||||
) |
||||
|
||||
func TestEncodeAndDecode(t *testing.T) { |
||||
|
||||
sum := sha256.Sum256([]byte("hello world123\n")) |
||||
|
||||
bech, err := bech32.ConvertAndEncode("shasum", sum[:]) |
||||
|
||||
if err != nil { |
||||
t.Error(err) |
||||
} |
||||
hrp, data, err := bech32.DecodeAndConvert(bech) |
||||
|
||||
if err != nil { |
||||
t.Error(err) |
||||
} |
||||
if hrp != "shasum" { |
||||
t.Error("Invalid hrp") |
||||
} |
||||
if !bytes.Equal(data, sum[:]) { |
||||
t.Error("Invalid decode") |
||||
} |
||||
} |
@ -0,0 +1,145 @@ |
||||
package common |
||||
|
||||
import ( |
||||
"database/sql/driver" |
||||
"encoding/hex" |
||||
"fmt" |
||||
"math/big" |
||||
|
||||
"github.com/ethereum/go-ethereum/common/hexutil" |
||||
"github.com/harmony-one/harmony/internal/bech32" |
||||
"github.com/harmony-one/harmony/internal/utils" |
||||
"golang.org/x/crypto/sha3" |
||||
) |
||||
|
||||
// Lengths of addresses in bytes.
|
||||
const ( |
||||
// AddressLength is the expected length of the address
|
||||
AddressLength = 20 |
||||
) |
||||
|
||||
// Address represents the 20 byte address of an Harmony account.
|
||||
type Address [AddressLength]byte |
||||
|
||||
// BytesToAddress returns Address with value b.
|
||||
// If b is larger than len(h), b will be cropped from the left.
|
||||
func BytesToAddress(b []byte) Address { |
||||
var a Address |
||||
a.SetBytes(b) |
||||
return a |
||||
} |
||||
|
||||
// BigToAddress returns Address with byte values of b.
|
||||
// If b is larger than len(h), b will be cropped from the left.
|
||||
func BigToAddress(b *big.Int) Address { return BytesToAddress(b.Bytes()) } |
||||
|
||||
// HexToAddress returns Address with byte values of s.
|
||||
// If s is larger than len(h), s will be cropped from the left.
|
||||
func HexToAddress(s string) Address { return BytesToAddress(utils.FromHex(s)) } |
||||
|
||||
// IsBech32Address verifies whether a string can represent a valid bech32-encoded
|
||||
// Harmony address or not.
|
||||
func IsBech32Address(s string) bool { |
||||
hrp, bytes, err := bech32.DecodeAndConvert(s) |
||||
if err != nil || (hrp != "one" && hrp != "tone") || len(bytes) != AddressLength { |
||||
return false |
||||
} |
||||
return true |
||||
} |
||||
|
||||
// Bytes gets the string representation of the underlying address.
|
||||
func (a Address) Bytes() []byte { return a[:] } |
||||
|
||||
// Big converts an address to a big integer.
|
||||
func (a Address) Big() *big.Int { return new(big.Int).SetBytes(a[:]) } |
||||
|
||||
// Hash converts an address to a hash by left-padding it with zeros.
|
||||
func (a Address) Hash() Hash { return BytesToHash(a[:]) } |
||||
|
||||
// Bech32 returns an bip0173-compliant string representation of the address.
|
||||
func (a Address) Bech32() string { |
||||
unchecksummed := hex.EncodeToString(a[:]) |
||||
sha := sha3.NewLegacyKeccak256() |
||||
sha.Write([]byte(unchecksummed)) |
||||
hash := sha.Sum(nil) |
||||
|
||||
result := []byte(unchecksummed) |
||||
for i := 0; i < len(result); i++ { |
||||
hashByte := hash[i/2] |
||||
if i%2 == 0 { |
||||
hashByte = hashByte >> 4 |
||||
} else { |
||||
hashByte &= 0xf |
||||
} |
||||
if result[i] > '9' && hashByte > 7 { |
||||
result[i] -= 32 |
||||
} |
||||
} |
||||
return "0x" + string(result) |
||||
} |
||||
|
||||
// String implements fmt.Stringer.
|
||||
func (a Address) String() string { |
||||
return a.Bech32() |
||||
} |
||||
|
||||
// Format implements fmt.Formatter, forcing the byte slice to be formatted as is,
|
||||
// without going through the stringer interface used for logging.
|
||||
func (a Address) Format(s fmt.State, c rune) { |
||||
fmt.Fprintf(s, "%"+string(c), a[:]) |
||||
} |
||||
|
||||
// SetBytes sets the address to the value of b.
|
||||
// If b is larger than len(a) it will panic.
|
||||
func (a *Address) SetBytes(b []byte) { |
||||
if len(b) > len(a) { |
||||
b = b[len(b)-AddressLength:] |
||||
} |
||||
copy(a[AddressLength-len(b):], b) |
||||
} |
||||
|
||||
// MarshalText returns the hex representation of a.
|
||||
func (a Address) MarshalText() ([]byte, error) { |
||||
return hexutil.Bytes(a[:]).MarshalText() |
||||
} |
||||
|
||||
// UnmarshalText parses a hash in hex syntax.
|
||||
func (a *Address) UnmarshalText(input []byte) error { |
||||
return hexutil.UnmarshalFixedText("Address", input, a[:]) |
||||
} |
||||
|
||||
// UnmarshalJSON parses a hash in hex syntax.
|
||||
func (a *Address) UnmarshalJSON(input []byte) error { |
||||
return hexutil.UnmarshalFixedJSON(addressT, input, a[:]) |
||||
} |
||||
|
||||
// Scan implements Scanner for database/sql.
|
||||
func (a *Address) Scan(src interface{}) error { |
||||
srcB, ok := src.([]byte) |
||||
if !ok { |
||||
return fmt.Errorf("can't scan %T into Address", src) |
||||
} |
||||
if len(srcB) != AddressLength { |
||||
return fmt.Errorf("can't scan []byte of len %d into Address, want %d", len(srcB), AddressLength) |
||||
} |
||||
copy(a[:], srcB) |
||||
return nil |
||||
} |
||||
|
||||
// Value implements valuer for database/sql.
|
||||
func (a Address) Value() (driver.Value, error) { |
||||
return a[:], nil |
||||
} |
||||
|
||||
// UnprefixedAddress allows marshaling an Address without 0x prefix.
|
||||
type UnprefixedAddress Address |
||||
|
||||
// UnmarshalText decodes the address from hex. The 0x prefix is optional.
|
||||
func (a *UnprefixedAddress) UnmarshalText(input []byte) error { |
||||
return hexutil.UnmarshalFixedUnprefixedText("UnprefixedAddress", input, a[:]) |
||||
} |
||||
|
||||
// MarshalText encodes the address as hex.
|
||||
func (a UnprefixedAddress) MarshalText() ([]byte, error) { |
||||
return []byte(hex.EncodeToString(a[:])), nil |
||||
} |
@ -0,0 +1,226 @@ |
||||
// Copyright 2015 The go-ethereum Authors
|
||||
// This file is part of the go-ethereum library.
|
||||
//
|
||||
// The go-ethereum library is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU Lesser General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// The go-ethereum library is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU Lesser General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Lesser General Public License
|
||||
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
package common |
||||
|
||||
import ( |
||||
"database/sql/driver" |
||||
"encoding/json" |
||||
"math/big" |
||||
"reflect" |
||||
"strings" |
||||
"testing" |
||||
) |
||||
|
||||
func TestIsBech32Address(t *testing.T) { |
||||
tests := []struct { |
||||
str string |
||||
exp bool |
||||
}{ |
||||
{"one1ay37rp2pc3kjarg7a322vu3sa8j9puahg679z3", true}, |
||||
{"one1fdv7u7rll9epgcqv9xxh9lhwq427nsqldp8ua9", true}, |
||||
{"tone1fdv7u7rll9epgcqv9xxh9lhwq427nsqlr5wca5", true}, |
||||
{"tone1fdv7u7rll9epgcqv9xxh9lhwq427nsqlr5wca1", false}, |
||||
{"xone1fdv7u7rll9epgcqv9xxh9lhwq427nsqlr5wca5", false}, |
||||
{"ne1fdv7u7rll9epgcqv9xxh9lhwq427nsqlr5wca5", false}, |
||||
{"1one1fdv7u7rll9epgcqv9xxh9lhwq427nsqlr5wca5", false}, |
||||
{"one2fdv7u7rll9epgcqv9xxh9lhwq427nsqlr5wca5", false}, |
||||
} |
||||
|
||||
for _, test := range tests { |
||||
if result := IsBech32Address(test.str); result != test.exp { |
||||
t.Errorf("IsBech32Address(%s) == %v; expected %v", |
||||
test.str, result, test.exp) |
||||
} |
||||
} |
||||
} |
||||
|
||||
func TestHashJsonValidation(t *testing.T) { |
||||
var tests = []struct { |
||||
Prefix string |
||||
Size int |
||||
Error string |
||||
}{ |
||||
{"", 62, "json: cannot unmarshal hex string without 0x prefix into Go value of type common.Hash"}, |
||||
{"0x", 66, "hex string has length 66, want 64 for common.Hash"}, |
||||
{"0x", 63, "json: cannot unmarshal hex string of odd length into Go value of type common.Hash"}, |
||||
{"0x", 0, "hex string has length 0, want 64 for common.Hash"}, |
||||
{"0x", 64, ""}, |
||||
{"0X", 64, ""}, |
||||
} |
||||
for _, test := range tests { |
||||
input := `"` + test.Prefix + strings.Repeat("0", test.Size) + `"` |
||||
var v Hash |
||||
err := json.Unmarshal([]byte(input), &v) |
||||
if err == nil { |
||||
if test.Error != "" { |
||||
t.Errorf("%s: error mismatch: have nil, want %q", input, test.Error) |
||||
} |
||||
} else { |
||||
if err.Error() != test.Error { |
||||
t.Errorf("%s: error mismatch: have %q, want %q", input, err, test.Error) |
||||
} |
||||
} |
||||
} |
||||
} |
||||
|
||||
func TestAddressUnmarshalJSON(t *testing.T) { |
||||
var tests = []struct { |
||||
Input string |
||||
ShouldErr bool |
||||
Output *big.Int |
||||
}{ |
||||
{"", true, nil}, |
||||
{`""`, true, nil}, |
||||
{`"0x"`, true, nil}, |
||||
{`"0x00"`, true, nil}, |
||||
{`"0xG000000000000000000000000000000000000000"`, true, nil}, |
||||
{`"0x0000000000000000000000000000000000000000"`, false, big.NewInt(0)}, |
||||
{`"0x0000000000000000000000000000000000000010"`, false, big.NewInt(16)}, |
||||
} |
||||
for i, test := range tests { |
||||
var v Address |
||||
err := json.Unmarshal([]byte(test.Input), &v) |
||||
if err != nil && !test.ShouldErr { |
||||
t.Errorf("test #%d: unexpected error: %v", i, err) |
||||
} |
||||
if err == nil { |
||||
if test.ShouldErr { |
||||
t.Errorf("test #%d: expected error, got none", i) |
||||
} |
||||
if got := new(big.Int).SetBytes(v.Bytes()); got.Cmp(test.Output) != 0 { |
||||
t.Errorf("test #%d: address mismatch: have %v, want %v", i, got, test.Output) |
||||
} |
||||
} |
||||
} |
||||
} |
||||
|
||||
func TestAddressHexChecksum(t *testing.T) { |
||||
var tests = []struct { |
||||
Input string |
||||
Output string |
||||
}{ |
||||
// Test cases from https://github.com/ethereum/EIPs/blob/master/EIPS/eip-55.md#specification
|
||||
{"0x5aaeb6053f3e94c9b9a09f33669435e7ef1beaed", "0x5aAeb6053F3E94C9b9A09f33669435E7Ef1BeAed"}, |
||||
{"0xfb6916095ca1df60bb79ce92ce3ea74c37c5d359", "0xfB6916095ca1df60bB79Ce92cE3Ea74c37c5d359"}, |
||||
{"0xdbf03b407c01e7cd3cbea99509d93f8dddc8c6fb", "0xdbF03B407c01E7cD3CBea99509d93f8DDDC8C6FB"}, |
||||
{"0xd1220a0cf47c7b9be7a2e6ba89f429762e7b9adb", "0xD1220A0cf47c7B9Be7A2E6BA89F429762e7b9aDb"}, |
||||
// Ensure that non-standard length input values are handled correctly
|
||||
{"0xa", "0x000000000000000000000000000000000000000A"}, |
||||
{"0x0a", "0x000000000000000000000000000000000000000A"}, |
||||
{"0x00a", "0x000000000000000000000000000000000000000A"}, |
||||
{"0x000000000000000000000000000000000000000a", "0x000000000000000000000000000000000000000A"}, |
||||
} |
||||
for i, test := range tests { |
||||
output := HexToAddress(test.Input).Bech32() |
||||
if output != test.Output { |
||||
t.Errorf("test #%d: failed to match when it should (%s != %s)", i, output, test.Output) |
||||
} |
||||
} |
||||
} |
||||
|
||||
func BenchmarkAddressBech32(b *testing.B) { |
||||
testAddr := HexToAddress("0x5aaeb6053f3e94c9b9a09f33669435e7ef1beaed") |
||||
for n := 0; n < b.N; n++ { |
||||
testAddr.Bech32() |
||||
} |
||||
} |
||||
|
||||
func TestAddress_Scan(t *testing.T) { |
||||
type args struct { |
||||
src interface{} |
||||
} |
||||
tests := []struct { |
||||
name string |
||||
args args |
||||
wantErr bool |
||||
}{ |
||||
{ |
||||
name: "working scan", |
||||
args: args{src: []byte{ |
||||
0xb2, 0x6f, 0x2b, 0x34, 0x2a, 0xab, 0x24, 0xbc, 0xf6, 0x3e, |
||||
0xa2, 0x18, 0xc6, 0xa9, 0x27, 0x4d, 0x30, 0xab, 0x9a, 0x15, |
||||
}}, |
||||
wantErr: false, |
||||
}, |
||||
{ |
||||
name: "non working scan", |
||||
args: args{src: int64(1234567890)}, |
||||
wantErr: true, |
||||
}, |
||||
{ |
||||
name: "invalid length scan", |
||||
args: args{src: []byte{ |
||||
0xb2, 0x6f, 0x2b, 0x34, 0x2a, 0xab, 0x24, 0xbc, 0xf6, 0x3e, |
||||
0xa2, 0x18, 0xc6, 0xa9, 0x27, 0x4d, 0x30, 0xab, 0x9a, |
||||
}}, |
||||
wantErr: true, |
||||
}, |
||||
} |
||||
for _, tt := range tests { |
||||
t.Run(tt.name, func(t *testing.T) { |
||||
a := &Address{} |
||||
if err := a.Scan(tt.args.src); (err != nil) != tt.wantErr { |
||||
t.Errorf("Address.Scan() error = %v, wantErr %v", err, tt.wantErr) |
||||
} |
||||
|
||||
if !tt.wantErr { |
||||
for i := range a { |
||||
if a[i] != tt.args.src.([]byte)[i] { |
||||
t.Errorf( |
||||
"Address.Scan() didn't scan the %d src correctly (have %X, want %X)", |
||||
i, a[i], tt.args.src.([]byte)[i], |
||||
) |
||||
} |
||||
} |
||||
} |
||||
}) |
||||
} |
||||
} |
||||
|
||||
func TestAddress_Value(t *testing.T) { |
||||
b := []byte{ |
||||
0xb2, 0x6f, 0x2b, 0x34, 0x2a, 0xab, 0x24, 0xbc, 0xf6, 0x3e, |
||||
0xa2, 0x18, 0xc6, 0xa9, 0x27, 0x4d, 0x30, 0xab, 0x9a, 0x15, |
||||
} |
||||
var usedA Address |
||||
usedA.SetBytes(b) |
||||
tests := []struct { |
||||
name string |
||||
a Address |
||||
want driver.Value |
||||
wantErr bool |
||||
}{ |
||||
{ |
||||
name: "Working value", |
||||
a: usedA, |
||||
want: b, |
||||
wantErr: false, |
||||
}, |
||||
} |
||||
for _, tt := range tests { |
||||
t.Run(tt.name, func(t *testing.T) { |
||||
got, err := tt.a.Value() |
||||
if (err != nil) != tt.wantErr { |
||||
t.Errorf("Address.Value() error = %v, wantErr %v", err, tt.wantErr) |
||||
return |
||||
} |
||||
if !reflect.DeepEqual(got, tt.want) { |
||||
t.Errorf("Address.Value() = %v, want %v", got, tt.want) |
||||
} |
||||
}) |
||||
} |
||||
} |
@ -0,0 +1,135 @@ |
||||
package common |
||||
|
||||
import ( |
||||
"database/sql/driver" |
||||
"encoding/hex" |
||||
"fmt" |
||||
"math/big" |
||||
"math/rand" |
||||
"reflect" |
||||
|
||||
"github.com/ethereum/go-ethereum/common/hexutil" |
||||
"github.com/harmony-one/harmony/internal/utils" |
||||
) |
||||
|
||||
// Lengths of hashes in bytes.
|
||||
const ( |
||||
// HashLength is the expected length of the hash
|
||||
HashLength = 32 |
||||
) |
||||
|
||||
var ( |
||||
hashT = reflect.TypeOf(Hash{}) |
||||
addressT = reflect.TypeOf(Address{}) |
||||
) |
||||
|
||||
// Hash represents the 32 byte Keccak256 hash of arbitrary data.
|
||||
type Hash [HashLength]byte |
||||
|
||||
// BytesToHash sets b to hash.
|
||||
// If b is larger than len(h), b will be cropped from the left.
|
||||
func BytesToHash(b []byte) Hash { |
||||
var h Hash |
||||
h.SetBytes(b) |
||||
return h |
||||
} |
||||
|
||||
// BigToHash sets byte representation of b to hash.
|
||||
// If b is larger than len(h), b will be cropped from the left.
|
||||
func BigToHash(b *big.Int) Hash { return BytesToHash(b.Bytes()) } |
||||
|
||||
// HexToHash sets byte representation of s to hash.
|
||||
// If b is larger than len(h), b will be cropped from the left.
|
||||
func HexToHash(s string) Hash { return BytesToHash(utils.FromHex(s)) } |
||||
|
||||
// Bytes gets the byte representation of the underlying hash.
|
||||
func (h Hash) Bytes() []byte { return h[:] } |
||||
|
||||
// Big converts a hash to a big integer.
|
||||
func (h Hash) Big() *big.Int { return new(big.Int).SetBytes(h[:]) } |
||||
|
||||
// Hex converts a hash to a hex string.
|
||||
func (h Hash) Hex() string { return hexutil.Encode(h[:]) } |
||||
|
||||
// TerminalString implements log.TerminalStringer, formatting a string for console
|
||||
// output during logging.
|
||||
func (h Hash) TerminalString() string { |
||||
return fmt.Sprintf("%x…%x", h[:3], h[29:]) |
||||
} |
||||
|
||||
// String implements the stringer interface and is used also by the logger when
|
||||
// doing full logging into a file.
|
||||
func (h Hash) String() string { |
||||
return h.Hex() |
||||
} |
||||
|
||||
// Format implements fmt.Formatter, forcing the byte slice to be formatted as is,
|
||||
// without going through the stringer interface used for logging.
|
||||
func (h Hash) Format(s fmt.State, c rune) { |
||||
fmt.Fprintf(s, "%"+string(c), h[:]) |
||||
} |
||||
|
||||
// UnmarshalText parses a hash in hex syntax.
|
||||
func (h *Hash) UnmarshalText(input []byte) error { |
||||
return hexutil.UnmarshalFixedText("Hash", input, h[:]) |
||||
} |
||||
|
||||
// UnmarshalJSON parses a hash in hex syntax.
|
||||
func (h *Hash) UnmarshalJSON(input []byte) error { |
||||
return hexutil.UnmarshalFixedJSON(hashT, input, h[:]) |
||||
} |
||||
|
||||
// MarshalText returns the hex representation of h.
|
||||
func (h Hash) MarshalText() ([]byte, error) { |
||||
return hexutil.Bytes(h[:]).MarshalText() |
||||
} |
||||
|
||||
// SetBytes sets the hash to the value of b.
|
||||
// If b is larger than len(h), b will be cropped from the left.
|
||||
func (h *Hash) SetBytes(b []byte) { |
||||
if len(b) > len(h) { |
||||
b = b[len(b)-HashLength:] |
||||
} |
||||
|
||||
copy(h[HashLength-len(b):], b) |
||||
} |
||||
|
||||
// Generate implements testing/quick.Generator.
|
||||
func (h Hash) Generate(rand *rand.Rand, size int) reflect.Value { |
||||
m := rand.Intn(len(h)) |
||||
for i := len(h) - 1; i > m; i-- { |
||||
h[i] = byte(rand.Uint32()) |
||||
} |
||||
return reflect.ValueOf(h) |
||||
} |
||||
|
||||
// Scan implements Scanner for database/sql.
|
||||
func (h *Hash) Scan(src interface{}) error { |
||||
srcB, ok := src.([]byte) |
||||
if !ok { |
||||
return fmt.Errorf("can't scan %T into Hash", src) |
||||
} |
||||
if len(srcB) != HashLength { |
||||
return fmt.Errorf("can't scan []byte of len %d into Hash, want %d", len(srcB), HashLength) |
||||
} |
||||
copy(h[:], srcB) |
||||
return nil |
||||
} |
||||
|
||||
// Value implements valuer for database/sql.
|
||||
func (h Hash) Value() (driver.Value, error) { |
||||
return h[:], nil |
||||
} |
||||
|
||||
// UnprefixedHash allows marshaling a Hash without 0x prefix.
|
||||
type UnprefixedHash Hash |
||||
|
||||
// UnmarshalText decodes the hash from hex. The 0x prefix is optional.
|
||||
func (h *UnprefixedHash) UnmarshalText(input []byte) error { |
||||
return hexutil.UnmarshalFixedUnprefixedText("UnprefixedHash", input, h[:]) |
||||
} |
||||
|
||||
// MarshalText encodes the hash as hex.
|
||||
func (h UnprefixedHash) MarshalText() ([]byte, error) { |
||||
return []byte(hex.EncodeToString(h[:])), nil |
||||
} |
@ -0,0 +1,110 @@ |
||||
package common |
||||
|
||||
import ( |
||||
"database/sql/driver" |
||||
"reflect" |
||||
"testing" |
||||
) |
||||
|
||||
func TestBytesConversion(t *testing.T) { |
||||
bytes := []byte{5} |
||||
hash := BytesToHash(bytes) |
||||
|
||||
var exp Hash |
||||
exp[31] = 5 |
||||
|
||||
if hash != exp { |
||||
t.Errorf("expected %x got %x", exp, hash) |
||||
} |
||||
} |
||||
|
||||
func TestHash_Scan(t *testing.T) { |
||||
type args struct { |
||||
src interface{} |
||||
} |
||||
tests := []struct { |
||||
name string |
||||
args args |
||||
wantErr bool |
||||
}{ |
||||
{ |
||||
name: "working scan", |
||||
args: args{src: []byte{ |
||||
0xb2, 0x6f, 0x2b, 0x34, 0x2a, 0xab, 0x24, 0xbc, 0xf6, 0x3e, |
||||
0xa2, 0x18, 0xc6, 0xa9, 0x27, 0x4d, 0x30, 0xab, 0x9a, 0x15, |
||||
0xa2, 0x18, 0xc6, 0xa9, 0x27, 0x4d, 0x30, 0xab, 0x9a, 0x15, |
||||
0x10, 0x00, |
||||
}}, |
||||
wantErr: false, |
||||
}, |
||||
{ |
||||
name: "non working scan", |
||||
args: args{src: int64(1234567890)}, |
||||
wantErr: true, |
||||
}, |
||||
{ |
||||
name: "invalid length scan", |
||||
args: args{src: []byte{ |
||||
0xb2, 0x6f, 0x2b, 0x34, 0x2a, 0xab, 0x24, 0xbc, 0xf6, 0x3e, |
||||
0xa2, 0x18, 0xc6, 0xa9, 0x27, 0x4d, 0x30, 0xab, 0x9a, 0x15, |
||||
0xa2, 0x18, 0xc6, 0xa9, 0x27, 0x4d, 0x30, 0xab, 0x9a, 0x15, |
||||
}}, |
||||
wantErr: true, |
||||
}, |
||||
} |
||||
for _, tt := range tests { |
||||
t.Run(tt.name, func(t *testing.T) { |
||||
h := &Hash{} |
||||
if err := h.Scan(tt.args.src); (err != nil) != tt.wantErr { |
||||
t.Errorf("Hash.Scan() error = %v, wantErr %v", err, tt.wantErr) |
||||
} |
||||
|
||||
if !tt.wantErr { |
||||
for i := range h { |
||||
if h[i] != tt.args.src.([]byte)[i] { |
||||
t.Errorf( |
||||
"Hash.Scan() didn't scan the %d src correctly (have %X, want %X)", |
||||
i, h[i], tt.args.src.([]byte)[i], |
||||
) |
||||
} |
||||
} |
||||
} |
||||
}) |
||||
} |
||||
} |
||||
|
||||
func TestHash_Value(t *testing.T) { |
||||
b := []byte{ |
||||
0xb2, 0x6f, 0x2b, 0x34, 0x2a, 0xab, 0x24, 0xbc, 0xf6, 0x3e, |
||||
0xa2, 0x18, 0xc6, 0xa9, 0x27, 0x4d, 0x30, 0xab, 0x9a, 0x15, |
||||
0xa2, 0x18, 0xc6, 0xa9, 0x27, 0x4d, 0x30, 0xab, 0x9a, 0x15, |
||||
0x10, 0x00, |
||||
} |
||||
var usedH Hash |
||||
usedH.SetBytes(b) |
||||
tests := []struct { |
||||
name string |
||||
h Hash |
||||
want driver.Value |
||||
wantErr bool |
||||
}{ |
||||
{ |
||||
name: "Working value", |
||||
h: usedH, |
||||
want: b, |
||||
wantErr: false, |
||||
}, |
||||
} |
||||
for _, tt := range tests { |
||||
t.Run(tt.name, func(t *testing.T) { |
||||
got, err := tt.h.Value() |
||||
if (err != nil) != tt.wantErr { |
||||
t.Errorf("Hash.Value() error = %v, wantErr %v", err, tt.wantErr) |
||||
return |
||||
} |
||||
if !reflect.DeepEqual(got, tt.want) { |
||||
t.Errorf("Hash.Value() = %v, want %v", got, tt.want) |
||||
} |
||||
}) |
||||
} |
||||
} |
Loading…
Reference in new issue