package apitypes import ( "database/sql" "encoding/json" "io/ioutil" "math/big" "os" "testing" ethCommon "github.com/ethereum/go-ethereum/common" "github.com/hermeznetwork/hermez-node/common" dbUtils "github.com/hermeznetwork/hermez-node/db" "github.com/iden3/go-iden3-crypto/babyjub" // nolint sqlite driver _ "github.com/mattn/go-sqlite3" "github.com/russross/meddler" "github.com/stretchr/testify/assert" ) var db *sql.DB func TestMain(m *testing.M) { // Register meddler meddler.Default = meddler.SQLite meddler.Register("bigint", dbUtils.BigIntMeddler{}) meddler.Register("bigintnull", dbUtils.BigIntNullMeddler{}) // Create temporary sqlite DB dir, err := ioutil.TempDir("", "db") if err != nil { panic(err) } db, err = sql.Open("sqlite3", dir+"sqlite.db") if err != nil { panic(err) } defer os.RemoveAll(dir) //nolint schema := `CREATE TABLE test (i BLOB);` if _, err := db.Exec(schema); err != nil { panic(err) } // Run tests result := m.Run() os.Exit(result) } func TestBigIntStrScannerValuer(t *testing.T) { // Clean DB _, err := db.Exec("delete from test") assert.NoError(t, err) // Example structs type bigInMeddlerStruct struct { I *big.Int `meddler:"i,bigint"` // note the bigint that instructs meddler to use BigIntMeddler } type bigIntStrStruct struct { I BigIntStr `meddler:"i"` // note that no meddler is specified, and Scan/Value will be used } type bigInMeddlerStructNil struct { I *big.Int `meddler:"i,bigintnull"` // note the bigint that instructs meddler to use BigIntNullMeddler } type bigIntStrStructNil struct { I *BigIntStr `meddler:"i"` // note that no meddler is specified, and Scan/Value will be used } // Not nil case // Insert into DB using meddler const x = int64(12345) fromMeddler := bigInMeddlerStruct{ I: big.NewInt(x), } err = meddler.Insert(db, "test", &fromMeddler) assert.NoError(t, err) // Read from DB using BigIntStr toBigIntStr := bigIntStrStruct{} err = meddler.QueryRow(db, &toBigIntStr, "select * from test") assert.NoError(t, err) assert.Equal(t, fromMeddler.I.String(), string(toBigIntStr.I)) // Clean DB _, err = db.Exec("delete from test") assert.NoError(t, err) // Insert into DB using BigIntStr fromBigIntStr := bigIntStrStruct{ I: "54321", } err = meddler.Insert(db, "test", &fromBigIntStr) assert.NoError(t, err) // Read from DB using meddler toMeddler := bigInMeddlerStruct{} err = meddler.QueryRow(db, &toMeddler, "select * from test") assert.NoError(t, err) assert.Equal(t, string(fromBigIntStr.I), toMeddler.I.String()) // Nil case // Clean DB _, err = db.Exec("delete from test") assert.NoError(t, err) // Insert into DB using meddler fromMeddlerNil := bigInMeddlerStructNil{ I: nil, } err = meddler.Insert(db, "test", &fromMeddlerNil) assert.NoError(t, err) // Read from DB using BigIntStr foo := BigIntStr("foo") toBigIntStrNil := bigIntStrStructNil{ I: &foo, // check that this will be set to nil, not because of not being initialized } err = meddler.QueryRow(db, &toBigIntStrNil, "select * from test") assert.NoError(t, err) assert.Nil(t, toBigIntStrNil.I) // Clean DB _, err = db.Exec("delete from test") assert.NoError(t, err) // Insert into DB using BigIntStr fromBigIntStrNil := bigIntStrStructNil{ I: nil, } err = meddler.Insert(db, "test", &fromBigIntStrNil) assert.NoError(t, err) // Read from DB using meddler toMeddlerNil := bigInMeddlerStructNil{ I: big.NewInt(x), // check that this will be set to nil, not because of not being initialized } err = meddler.QueryRow(db, &toMeddlerNil, "select * from test") assert.NoError(t, err) assert.Nil(t, toMeddlerNil.I) } func TestStrBigInt(t *testing.T) { type testStrBigInt struct { I StrBigInt } from := []byte(`{"I":"4"}`) to := &testStrBigInt{} assert.NoError(t, json.Unmarshal(from, to)) assert.Equal(t, big.NewInt(4), (*big.Int)(&to.I)) } func TestStrHezEthAddr(t *testing.T) { type testStrHezEthAddr struct { I StrHezEthAddr } withoutHez := "0xaa942cfcd25ad4d90a62358b0dd84f33b398262a" from := []byte(`{"I":"hez:` + withoutHez + `"}`) var addr ethCommon.Address if err := addr.UnmarshalText([]byte(withoutHez)); err != nil { panic(err) } to := &testStrHezEthAddr{} assert.NoError(t, json.Unmarshal(from, to)) assert.Equal(t, addr, ethCommon.Address(to.I)) } func TestStrHezBJJ(t *testing.T) { type testStrHezBJJ struct { I StrHezBJJ } priv := babyjub.NewRandPrivKey() hezBjj := NewHezBJJ(priv.Public().Compress()) from := []byte(`{"I":"` + hezBjj + `"}`) to := &testStrHezBJJ{} assert.NoError(t, json.Unmarshal(from, to)) assert.Equal(t, priv.Public().Compress(), (babyjub.PublicKeyComp)(to.I)) } func TestStrHezIdx(t *testing.T) { type testStrHezIdx struct { I StrHezIdx } from := []byte(`{"I":"hez:foo:4"}`) to := &testStrHezIdx{} assert.NoError(t, json.Unmarshal(from, to)) assert.Equal(t, common.Idx(4), common.Idx(to.I)) } func TestHezEthAddr(t *testing.T) { // Clean DB _, err := db.Exec("delete from test") assert.NoError(t, err) // Example structs type ethAddrStruct struct { I ethCommon.Address `meddler:"i"` } type hezEthAddrStruct struct { I HezEthAddr `meddler:"i"` } type ethAddrStructNil struct { I *ethCommon.Address `meddler:"i"` } type hezEthAddrStructNil struct { I *HezEthAddr `meddler:"i"` } // Not nil case // Insert into DB using ethCommon.Address Scan/Value fromEth := ethAddrStruct{ I: ethCommon.BigToAddress(big.NewInt(73737373)), } err = meddler.Insert(db, "test", &fromEth) assert.NoError(t, err) // Read from DB using HezEthAddr Scan/Value toHezEth := hezEthAddrStruct{} err = meddler.QueryRow(db, &toHezEth, "select * from test") assert.NoError(t, err) assert.Equal(t, NewHezEthAddr(fromEth.I), toHezEth.I) // Clean DB _, err = db.Exec("delete from test") assert.NoError(t, err) // Insert into DB using HezEthAddr Scan/Value fromHezEth := hezEthAddrStruct{ I: NewHezEthAddr(ethCommon.BigToAddress(big.NewInt(3786872586))), } err = meddler.Insert(db, "test", &fromHezEth) assert.NoError(t, err) // Read from DB using ethCommon.Address Scan/Value toEth := ethAddrStruct{} err = meddler.QueryRow(db, &toEth, "select * from test") assert.NoError(t, err) assert.Equal(t, fromHezEth.I, NewHezEthAddr(toEth.I)) // Nil case // Clean DB _, err = db.Exec("delete from test") assert.NoError(t, err) // Insert into DB using ethCommon.Address Scan/Value fromEthNil := ethAddrStructNil{ I: nil, } err = meddler.Insert(db, "test", &fromEthNil) assert.NoError(t, err) // Read from DB using HezEthAddr Scan/Value foo := HezEthAddr("foo") toHezEthNil := hezEthAddrStructNil{ I: &foo, // check that this will be set to nil, not because of not being initialized } err = meddler.QueryRow(db, &toHezEthNil, "select * from test") assert.NoError(t, err) assert.Nil(t, toHezEthNil.I) // Clean DB _, err = db.Exec("delete from test") assert.NoError(t, err) // Insert into DB using HezEthAddr Scan/Value fromHezEthNil := hezEthAddrStructNil{ I: nil, } err = meddler.Insert(db, "test", &fromHezEthNil) assert.NoError(t, err) // Read from DB using ethCommon.Address Scan/Value fooAddr := ethCommon.BigToAddress(big.NewInt(1)) toEthNil := ethAddrStructNil{ I: &fooAddr, // check that this will be set to nil, not because of not being initialized } err = meddler.QueryRow(db, &toEthNil, "select * from test") assert.NoError(t, err) assert.Nil(t, toEthNil.I) } func TestHezBJJ(t *testing.T) { // Clean DB _, err := db.Exec("delete from test") assert.NoError(t, err) // Example structs type bjjStruct struct { I babyjub.PublicKeyComp `meddler:"i"` } type hezBJJStruct struct { I HezBJJ `meddler:"i"` } type bjjStructNil struct { I *babyjub.PublicKeyComp `meddler:"i"` } type hezBJJStructNil struct { I *HezBJJ `meddler:"i"` } // Not nil case // Insert into DB using *babyjub.PublicKeyComp Scan/Value priv := babyjub.NewRandPrivKey() fromBJJ := bjjStruct{ I: priv.Public().Compress(), } err = meddler.Insert(db, "test", &fromBJJ) assert.NoError(t, err) // Read from DB using HezBJJ Scan/Value toHezBJJ := hezBJJStruct{} err = meddler.QueryRow(db, &toHezBJJ, "select * from test") assert.NoError(t, err) assert.Equal(t, NewHezBJJ(fromBJJ.I), toHezBJJ.I) // Clean DB _, err = db.Exec("delete from test") assert.NoError(t, err) // Insert into DB using HezBJJ Scan/Value fromHezBJJ := hezBJJStruct{ I: NewHezBJJ(priv.Public().Compress()), } err = meddler.Insert(db, "test", &fromHezBJJ) assert.NoError(t, err) // Read from DB using *babyjub.PublicKeyComp Scan/Value toBJJ := bjjStruct{} err = meddler.QueryRow(db, &toBJJ, "select * from test") assert.NoError(t, err) assert.Equal(t, fromHezBJJ.I, NewHezBJJ(toBJJ.I)) // Nil case // Clean DB _, err = db.Exec("delete from test") assert.NoError(t, err) // Insert into DB using *babyjub.PublicKeyComp Scan/Value fromBJJNil := bjjStructNil{ I: nil, } err = meddler.Insert(db, "test", &fromBJJNil) assert.NoError(t, err) // Read from DB using HezBJJ Scan/Value foo := HezBJJ("foo") toHezBJJNil := hezBJJStructNil{ I: &foo, // check that this will be set to nil, not because of not being initialized } err = meddler.QueryRow(db, &toHezBJJNil, "select * from test") assert.NoError(t, err) assert.Nil(t, toHezBJJNil.I) // Clean DB _, err = db.Exec("delete from test") assert.NoError(t, err) // Insert into DB using HezBJJ Scan/Value fromHezBJJNil := hezBJJStructNil{ I: nil, } err = meddler.Insert(db, "test", &fromHezBJJNil) assert.NoError(t, err) // Read from DB using *babyjub.PublicKeyComp Scan/Value bjjComp := priv.Public().Compress() toBJJNil := bjjStructNil{ I: &bjjComp, // check that this will be set to nil, not because of not being initialized } err = meddler.QueryRow(db, &toBJJNil, "select * from test") assert.NoError(t, err) assert.Nil(t, toBJJNil.I) } func TestEthSignature(t *testing.T) { // Clean DB _, err := db.Exec("delete from test") assert.NoError(t, err) // Example structs type ethSignStruct struct { I []byte `meddler:"i"` } type hezEthSignStruct struct { I EthSignature `meddler:"i"` } type hezEthSignStructNil struct { I *EthSignature `meddler:"i"` } // Not nil case // Insert into DB using []byte Scan/Value s := "someRandomFooForYou" fromEth := ethSignStruct{ I: []byte(s), } err = meddler.Insert(db, "test", &fromEth) assert.NoError(t, err) // Read from DB using EthSignature Scan/Value toHezEth := hezEthSignStruct{} err = meddler.QueryRow(db, &toHezEth, "select * from test") assert.NoError(t, err) assert.Equal(t, NewEthSignature(fromEth.I), &toHezEth.I) // Clean DB _, err = db.Exec("delete from test") assert.NoError(t, err) // Insert into DB using EthSignature Scan/Value fromHezEth := hezEthSignStruct{ I: *NewEthSignature([]byte(s)), } err = meddler.Insert(db, "test", &fromHezEth) assert.NoError(t, err) // Read from DB using []byte Scan/Value toEth := ethSignStruct{} err = meddler.QueryRow(db, &toEth, "select * from test") assert.NoError(t, err) assert.Equal(t, &fromHezEth.I, NewEthSignature(toEth.I)) // Nil case // Clean DB _, err = db.Exec("delete from test") assert.NoError(t, err) // Insert into DB using []byte Scan/Value fromEthNil := ethSignStruct{ I: nil, } err = meddler.Insert(db, "test", &fromEthNil) assert.NoError(t, err) // Read from DB using EthSignature Scan/Value foo := EthSignature("foo") toHezEthNil := hezEthSignStructNil{ I: &foo, // check that this will be set to nil, not because of not being initialized } err = meddler.QueryRow(db, &toHezEthNil, "select * from test") assert.NoError(t, err) assert.Nil(t, toHezEthNil.I) // Clean DB _, err = db.Exec("delete from test") assert.NoError(t, err) // Insert into DB using EthSignature Scan/Value fromHezEthNil := hezEthSignStructNil{ I: nil, } err = meddler.Insert(db, "test", &fromHezEthNil) assert.NoError(t, err) // Read from DB using []byte Scan/Value toEthNil := ethSignStruct{ I: []byte(s), // check that this will be set to nil, not because of not being initialized } err = meddler.QueryRow(db, &toEthNil, "select * from test") assert.NoError(t, err) assert.Nil(t, toEthNil.I) }