1// SPDX-License-Identifier: ISC
2// Copyright (c) 2014-2020 Bitmark Inc.
3// Use of this source code is governed by an ISC
4// license that can be found in the LICENSE file.
5
6package transactionrecord_test
7
8import (
9	"encoding/json"
10	"fmt"
11	"testing"
12
13	"github.com/bitmark-inc/bitmarkd/fault"
14	"github.com/bitmark-inc/bitmarkd/transactionrecord"
15	"github.com/bitmark-inc/bitmarkd/util"
16)
17
18// test invalid asset identifiers
19func TestInvalidAssetIdentifiers(t *testing.T) {
20
21	invalid := []string{
22		"",
23		"4b",                         // one byte
24		"4bf",                        // odd number of chars
25		"4473fb34cc05ed9599935a0098", // truncated
26		"4473fb34cc05ed9599935a0098ce060dfa546f40932dd7b40d35f8fe5cd6a4ff26f3dbf8ffc86ee8eb6480facfd83f3e20d69bf1e764a59256cf79b89531de3",    // just one short
27		"4473fb34cc05ed9599935a0098ce060dfa546f40932dd7b40d35f8fe5cd6a4ff26f3dbf8ffc86ee8eb6480facfd83f3e20d69bf1e764a59256cf79b89531de379",  // just one char over
28		"4473fb34cc05ed9599935a0098ce060dfa546f40932dd7b40d35f8fe5cd6a4ff26f3dbf8ffc86ee8eb6480facfd83f3e20d69bf1e764a59256cf79b89531de3745", // just one byte over
29
30		"BAM04473fb34cc05ed9599935a0098ce060dfa546f40932dd7b40d35f8fe5cd6a4ff26f3dbf8ffc86ee8eb6480facfd83f3e20d69bf1e764a59256cf79b89531de37", // bad prefix
31		"ABM04473fb34cc05ed9599935a0098ce060dfa546f40932dd7b40d35f8fe5cd6a4ff26f3dbf8ffc86ee8eb6480facfd83f3e20d69bf1e764a59256cf79b89531de37", // bad prefix
32		"QWRT4473fb34cc05ed9599935a0098ce060dfa546f40932dd7b40d35f8fe5cd6a4ff26f3dbf8ffc86ee8eb6480facfd83f3e20d69bf1e764a59256cf79b89531de37", // bad prefix
33
34		"4473fb34cc05ed9599x35a0098ce060dfa546f40932dd7b40d35f8fe5cd6a4ff26f3dbf8ffc86ee8eb6480facfd83f3e20d69bf1e764a59256cf79b89531de37", // invalid hex char x
35		"4473fb34cc05ed9599X35a0098ce060dfa546f40932dd7b40d35f8fe5cd6a4ff26f3dbf8ffc86ee8eb6480facfd83f3e20d69bf1e764a59256cf79b89531de37", // invalid hex char X
36		"4473fb34cc05ed9599k35a0098ce060dfa546f40932dd7b40d35f8fe5cd6a4ff26f3dbf8ffc86ee8eb6480facfd83f3e20d69bf1e764a59256cf79b89531de37", // invalid hex char k
37		"4473fb34cc05ed9599K35a0098ce060dfa546f40932dd7b40d35f8fe5cd6a4ff26f3dbf8ffc86ee8eb6480facfd83f3e20d69bf1e764a59256cf79b89531de37", // invalid hex char K
38	}
39
40	for i, textAssetIdentifier := range invalid {
41		var link transactionrecord.AssetIdentifier
42		n, err := fmt.Sscan(textAssetIdentifier, &link)
43		if fault.NotAssetId != err {
44			t.Errorf("%d: testing: %q", i, textAssetIdentifier)
45			t.Errorf("%d: expected fault.NotAssetIdentifier but got: %v", i, err)
46			return
47		}
48		if 0 != n {
49			t.Errorf("%d: testing: %q", i, textAssetIdentifier)
50			t.Errorf("%d: hex to link scanned: %d  expected: 0", i, n)
51			return
52		}
53	}
54}
55
56// test asset id conversion
57func TestAssetIdentifier(t *testing.T) {
58
59	expectedAssetIdentifier := transactionrecord.AssetIdentifier{
60		0x37, 0xde, 0x31, 0x95, 0xb8, 0x79, 0xcf, 0x56,
61		0x92, 0xa5, 0x64, 0xe7, 0xf1, 0x9b, 0xd6, 0x20,
62		0x3e, 0x3f, 0xd8, 0xcf, 0xfa, 0x80, 0x64, 0xeb,
63		0xe8, 0x6e, 0xc8, 0xff, 0xf8, 0xdb, 0xf3, 0x26,
64		0xff, 0xa4, 0xd6, 0x5c, 0xfe, 0xf8, 0x35, 0x0d,
65		0xb4, 0xd7, 0x2d, 0x93, 0x40, 0x6f, 0x54, 0xfa,
66		0x0d, 0x06, 0xce, 0x98, 0x00, 0x5a, 0x93, 0x99,
67		0x95, 0xed, 0x05, 0xcc, 0x34, 0xfb, 0x73, 0x44,
68	}
69
70	textAssetIdentifier := "37de3195b879cf5692a564e7f19bd6203e3fd8cffa8064ebe86ec8fff8dbf326ffa4d65cfef8350db4d72d93406f54fa0d06ce98005a939995ed05cc34fb7344"
71
72	if expectedAssetIdentifier.String() != textAssetIdentifier {
73		t.Errorf("asset id(%%s): %s  expected: %s", expectedAssetIdentifier, textAssetIdentifier)
74	}
75
76	if fmt.Sprintf("%v", expectedAssetIdentifier) != textAssetIdentifier {
77		t.Errorf("asset id(%%v): %v  expected: %s", expectedAssetIdentifier, textAssetIdentifier)
78	}
79
80	if fmt.Sprintf("%#v", expectedAssetIdentifier) != "<asset:"+textAssetIdentifier+">" {
81		t.Errorf("asset id(%%#v): %#v  expected: %s", expectedAssetIdentifier, "<asset:"+textAssetIdentifier+">")
82	}
83
84	var asset transactionrecord.AssetIdentifier
85	n, err := fmt.Sscan("37de3195b879cf5692a564e7f19bd6203e3fd8cffa8064ebe86ec8fff8dbf326ffa4d65cfef8350db4d72d93406f54fa0d06ce98005a939995ed05cc34fb7344", &asset)
86	if nil != err {
87		t.Fatalf("hex to link error: %s", err)
88	}
89	if 1 != n {
90		t.Fatalf("hex to link scanned: %d  expected: 1", n)
91	}
92
93	if asset != expectedAssetIdentifier {
94		t.Errorf("asset: %#v  expected: %#v", asset, expectedAssetIdentifier)
95		t.Errorf("*** GENERATED asset:\n%s", util.FormatBytes("expectedAssetIdentifier", asset[:]))
96	}
97
98	// check JSON conversion
99	expectedJSON := `{"AssetIdentifier":"37de3195b879cf5692a564e7f19bd6203e3fd8cffa8064ebe86ec8fff8dbf326ffa4d65cfef8350db4d72d93406f54fa0d06ce98005a939995ed05cc34fb7344"}`
100
101	item := struct {
102		AssetIdentifier transactionrecord.AssetIdentifier
103	}{
104		asset,
105	}
106	convertedJSON, err := json.Marshal(item)
107	if nil != err {
108		t.Fatalf("marshal json error: %s", err)
109	}
110	if expectedJSON != string(convertedJSON) {
111		t.Errorf("JSON converted: %q", convertedJSON)
112		t.Errorf("     expected:  %q", expectedJSON)
113	}
114
115	// test json unmarshal
116	var newItem struct {
117		AssetIdentifier transactionrecord.AssetIdentifier
118	}
119	err = json.Unmarshal([]byte(expectedJSON), &newItem)
120	if nil != err {
121		t.Fatalf("unmarshal json error: %s", err)
122	}
123
124	if newItem.AssetIdentifier != expectedAssetIdentifier {
125		t.Errorf("link: %#v  expected: %#v", newItem.AssetIdentifier, expectedAssetIdentifier)
126	}
127
128}
129
130// test asset id bytes
131func TestAssetIdentifierFromBytes(t *testing.T) {
132
133	expectedAssetId := transactionrecord.AssetIdentifier{
134		0x37, 0xde, 0x31, 0x95, 0xb8, 0x79, 0xcf, 0x56,
135		0x92, 0xa5, 0x64, 0xe7, 0xf1, 0x9b, 0xd6, 0x20,
136		0x3e, 0x3f, 0xd8, 0xcf, 0xfa, 0x80, 0x64, 0xeb,
137		0xe8, 0x6e, 0xc8, 0xff, 0xf8, 0xdb, 0xf3, 0x26,
138		0xff, 0xa4, 0xd6, 0x5c, 0xfe, 0xf8, 0x35, 0x0d,
139		0xb4, 0xd7, 0x2d, 0x93, 0x40, 0x6f, 0x54, 0xfa,
140		0x0d, 0x06, 0xce, 0x98, 0x00, 0x5a, 0x93, 0x99,
141		0x95, 0xed, 0x05, 0xcc, 0x34, 0xfb, 0x73, 0x44,
142	}
143
144	valid := []byte{
145		0x37, 0xde, 0x31, 0x95, 0xb8, 0x79, 0xcf, 0x56,
146		0x92, 0xa5, 0x64, 0xe7, 0xf1, 0x9b, 0xd6, 0x20,
147		0x3e, 0x3f, 0xd8, 0xcf, 0xfa, 0x80, 0x64, 0xeb,
148		0xe8, 0x6e, 0xc8, 0xff, 0xf8, 0xdb, 0xf3, 0x26,
149		0xff, 0xa4, 0xd6, 0x5c, 0xfe, 0xf8, 0x35, 0x0d,
150		0xb4, 0xd7, 0x2d, 0x93, 0x40, 0x6f, 0x54, 0xfa,
151		0x0d, 0x06, 0xce, 0x98, 0x00, 0x5a, 0x93, 0x99,
152		0x95, 0xed, 0x05, 0xcc, 0x34, 0xfb, 0x73, 0x44,
153	}
154
155	var assetId transactionrecord.AssetIdentifier
156	err := transactionrecord.AssetIdentifierFromBytes(&assetId, valid)
157	if nil != err {
158		t.Fatalf("AssetIdentifierFromBytes error: %s", err)
159	}
160
161	if assetId != expectedAssetId {
162		t.Fatalf("assetIdentifier expected: %v  actual: %v", expectedAssetId, assetId)
163	}
164
165	err = transactionrecord.AssetIdentifierFromBytes(&assetId, valid[1:])
166	if fault.NotAssetId != err {
167		t.Fatalf("AssetIdentifierFromBytes error: %s", err)
168	}
169}
170