kaspad/util/gcs/gcs_test.go
stasatdaglabs 3ace16ad23 [DEV-134] Implement Continuous Integration (#105)
* [DEV-134] Implement Continuous Integration

Squashed commit:

[5e41d830] Dev 223 fix txindex (#100)

* [DEV-201] In handleGetBlockDAGInfo calculate difficulty by the tip with the lowest bits

* [DEV-202] Move VirtualBlock.GetUTXOEntry to BlockDAG

* [DEV-203] Move VirtualBlock.SelectedTip() to BlockDAG

* [DEV-203] Move VirtualBlock.SelectedTip() to BlockDAG

* [DEV-204] Unexport VirtualBlock() and add CalcMedianTime method for DAG

* [DEV-204] add explanation about difficulty in CurrentBits() comment

* [DEV-204] unexport VirtualBlock type

* [DEV-223] make applyUTXOChanges return pastUTXOResults

* [DEV-223] add bluestxdata for current block as well

* [DEV-223] re-design tx index

* [DEV-223] edit txindex comments

* [DEV-223] rename BluesTxData -> AcceptedTxData, and return from applyUTXOChanges only transactions that got accepted

* [DEV-223] add unit test for txindex

* [DEV-223] fix comments and unite blueTransaction and AcceptedTxData to one type

* [DEV-223] use bucket cursor for dbFetchFirstTxRegion

* [DEV-223] use the same cursor instance for dbFetchFirstTxRegion

* [DEV-223] write in dbFetchFirstTxRegion's comment that it returns the first block region

* [DEV-223] rename type BlueBlockTransaction to TxWithBlockHash

* [DEV-223] add named returned value for applyUTXOChanges

[4c95e293] [DEV-134] Made golint ignore the vendor directory.

[21736dbc] [DEV-134] Renamed ExampleBlockChain_ProcessBlock to ExampleBlockDAG_ProcessBlock to satisfy go vet.

[beea6486] [DEV-134] Removed pushing the built docker to a remove repository. That's unnecessary at this stage.

[bee911ed] [DEV-134] Made all precompilation checks run on everything instead of only the root dir.

[585f92ae] [DEV-134] Added "github.com/pkg/errors" to dep.

[5f02f570] [DEV-134] -vendor-only is written with only one hyphen.

[3eee7f95] [DEV-134] go vet instead of go tool vet.

[0c2d4343] [DEV-134] Split all the pre-compile checks to separate lines to be able to tell which of them is failing.

[780519c8] [DEV-134] Ran gofmt on everything.

[8247146b] Dev 223 fix txindex (#100)

* [DEV-201] In handleGetBlockDAGInfo calculate difficulty by the tip with the lowest bits

* [DEV-202] Move VirtualBlock.GetUTXOEntry to BlockDAG

* [DEV-203] Move VirtualBlock.SelectedTip() to BlockDAG

* [DEV-203] Move VirtualBlock.SelectedTip() to BlockDAG

* [DEV-204] Unexport VirtualBlock() and add CalcMedianTime method for DAG

* [DEV-204] add explanation about difficulty in CurrentBits() comment

* [DEV-204] unexport VirtualBlock type

* [DEV-223] make applyUTXOChanges return pastUTXOResults

* [DEV-223] add bluestxdata for current block as well

* [DEV-223] re-design tx index

* [DEV-223] edit txindex comments

* [DEV-223] rename BluesTxData -> AcceptedTxData, and return from applyUTXOChanges only transactions that got accepted

* [DEV-223] add unit test for txindex

* [DEV-223] fix comments and unite blueTransaction and AcceptedTxData to one type

* [DEV-223] use bucket cursor for dbFetchFirstTxRegion

* [DEV-223] use the same cursor instance for dbFetchFirstTxRegion

* [DEV-223] write in dbFetchFirstTxRegion's comment that it returns the first block region

* [DEV-223] rename type BlueBlockTransaction to TxWithBlockHash

* [DEV-223] add named returned value for applyUTXOChanges

[bff68aa3] [DEV-134] Gave executable permission to deploy.sh

[638a99d9] [DEV-134] Added jenkinsfile and deploy script.

* [DEV-134] Added a robust testing script.

* [DEV-134] Fixed a bash-ism.

* [DEV-134] Disabled testing with coverage for now.

* [DEV-134] Disabled golint and removed removing debug symbols.

* [DEV-134] Disabled aligncheck.

* [DEV-134] Disabled structcheck and varcheck.

* [DEV-134] Added "don't inline functions" to compiler flags for testing.

* [DEV-134] Made build fail if gofmt prints out anything.

* [DEV-134] Fixed misleading comment.

* [DEV-134] Added comments to test.sh.

* [DEV-134] Renamed tm to measure_runtime and removed do_ prefixes from functions.

* [DEV-134] Fixed gofmt line in build script.

* [DEV-134] Fixed gofmt some more.

* [DEV-134]  Fixed gofmt not actually failing due to logical or.
2018-10-25 18:58:41 +03:00

284 lines
7.6 KiB
Go

// Copyright (c) 2016-2017 The btcsuite developers
// Copyright (c) 2016-2017 The Lightning Network Developers
// Use of this source code is governed by an ISC
// license that can be found in the LICENSE file.
package gcs_test
import (
"bytes"
"encoding/binary"
"github.com/daglabs/btcd/util/gcs"
"math/rand"
"testing"
)
var (
// No need to allocate an err variable in every test
err error
// Collision probability for the tests (1/2**20)
P = uint8(20)
// Filters are conserved between tests but we must define with an
// interface which functions we're testing because the gcsFilter type
// isn't exported
filter, filter2, filter3, filter4, filter5 *gcs.Filter
// We need to use the same key for building and querying the filters
key [gcs.KeySize]byte
// List of values for building a filter
contents = [][]byte{
[]byte("Alex"),
[]byte("Bob"),
[]byte("Charlie"),
[]byte("Dick"),
[]byte("Ed"),
[]byte("Frank"),
[]byte("George"),
[]byte("Harry"),
[]byte("Ilya"),
[]byte("John"),
[]byte("Kevin"),
[]byte("Larry"),
[]byte("Michael"),
[]byte("Nate"),
[]byte("Owen"),
[]byte("Paul"),
[]byte("Quentin"),
}
// List of values for querying a filter using MatchAny()
contents2 = [][]byte{
[]byte("Alice"),
[]byte("Betty"),
[]byte("Charmaine"),
[]byte("Donna"),
[]byte("Edith"),
[]byte("Faina"),
[]byte("Georgia"),
[]byte("Hannah"),
[]byte("Ilsbeth"),
[]byte("Jennifer"),
[]byte("Kayla"),
[]byte("Lena"),
[]byte("Michelle"),
[]byte("Natalie"),
[]byte("Ophelia"),
[]byte("Peggy"),
[]byte("Queenie"),
}
)
// TestGCSFilterBuild builds a test filter with a randomized key. For Bitcoin
// use, deterministic filter generation is desired. Therefore, a key that's
// derived deterministically would be required.
func TestGCSFilterBuild(t *testing.T) {
for i := 0; i < gcs.KeySize; i += 4 {
binary.BigEndian.PutUint32(key[i:], rand.Uint32())
}
filter, err = gcs.BuildGCSFilter(P, key, contents)
if err != nil {
t.Fatalf("Filter build failed: %s", err.Error())
}
}
// TestGCSFilterCopy deserializes and serializes a filter to create a copy.
func TestGCSFilterCopy(t *testing.T) {
serialized2, err := filter.Bytes()
if err != nil {
t.Fatalf("Filter Bytes() failed: %v", err)
}
filter2, err = gcs.FromBytes(filter.N(), P, serialized2)
if err != nil {
t.Fatalf("Filter copy failed: %s", err.Error())
}
serialized3, err := filter.NBytes()
if err != nil {
t.Fatalf("Filter NBytes() failed: %v", err)
}
filter3, err = gcs.FromNBytes(filter.P(), serialized3)
if err != nil {
t.Fatalf("Filter copy failed: %s", err.Error())
}
serialized4, err := filter.PBytes()
if err != nil {
t.Fatalf("Filter PBytes() failed: %v", err)
}
filter4, err = gcs.FromPBytes(filter.N(), serialized4)
if err != nil {
t.Fatalf("Filter copy failed: %s", err.Error())
}
serialized5, err := filter.NPBytes()
if err != nil {
t.Fatalf("Filter NPBytes() failed: %v", err)
}
filter5, err = gcs.FromNPBytes(serialized5)
if err != nil {
t.Fatalf("Filter copy failed: %s", err.Error())
}
}
// TestGCSFilterMetadata checks that the filter metadata is built and copied
// correctly.
func TestGCSFilterMetadata(t *testing.T) {
if filter.P() != P {
t.Fatal("P not correctly stored in filter metadata")
}
if filter.N() != uint32(len(contents)) {
t.Fatal("N not correctly stored in filter metadata")
}
if filter.P() != filter2.P() {
t.Fatal("P doesn't match between copied filters")
}
if filter.P() != filter3.P() {
t.Fatal("P doesn't match between copied filters")
}
if filter.P() != filter4.P() {
t.Fatal("P doesn't match between copied filters")
}
if filter.P() != filter5.P() {
t.Fatal("P doesn't match between copied filters")
}
if filter.N() != filter2.N() {
t.Fatal("N doesn't match between copied filters")
}
if filter.N() != filter3.N() {
t.Fatal("N doesn't match between copied filters")
}
if filter.N() != filter4.N() {
t.Fatal("N doesn't match between copied filters")
}
if filter.N() != filter5.N() {
t.Fatal("N doesn't match between copied filters")
}
serialized, err := filter.Bytes()
if err != nil {
t.Fatalf("Filter Bytes() failed: %v", err)
}
serialized2, err := filter2.Bytes()
if err != nil {
t.Fatalf("Filter Bytes() failed: %v", err)
}
if !bytes.Equal(serialized, serialized2) {
t.Fatal("Bytes don't match between copied filters")
}
serialized3, err := filter3.Bytes()
if err != nil {
t.Fatalf("Filter Bytes() failed: %v", err)
}
if !bytes.Equal(serialized, serialized3) {
t.Fatal("Bytes don't match between copied filters")
}
serialized4, err := filter3.Bytes()
if err != nil {
t.Fatalf("Filter Bytes() failed: %v", err)
}
if !bytes.Equal(serialized, serialized4) {
t.Fatal("Bytes don't match between copied filters")
}
serialized5, err := filter5.Bytes()
if err != nil {
t.Fatalf("Filter Bytes() failed: %v", err)
}
if !bytes.Equal(serialized, serialized5) {
t.Fatal("Bytes don't match between copied filters")
}
}
// TestGCSFilterMatch checks that both the built and copied filters match
// correctly, logging any false positives without failing on them.
func TestGCSFilterMatch(t *testing.T) {
match, err := filter.Match(key, []byte("Nate"))
if err != nil {
t.Fatalf("Filter match failed: %s", err.Error())
}
if !match {
t.Fatal("Filter didn't match when it should have!")
}
match, err = filter2.Match(key, []byte("Nate"))
if err != nil {
t.Fatalf("Filter match failed: %s", err.Error())
}
if !match {
t.Fatal("Filter didn't match when it should have!")
}
match, err = filter.Match(key, []byte("Quentin"))
if err != nil {
t.Fatalf("Filter match failed: %s", err.Error())
}
if !match {
t.Fatal("Filter didn't match when it should have!")
}
match, err = filter2.Match(key, []byte("Quentin"))
if err != nil {
t.Fatalf("Filter match failed: %s", err.Error())
}
if !match {
t.Fatal("Filter didn't match when it should have!")
}
match, err = filter.Match(key, []byte("Nates"))
if err != nil {
t.Fatalf("Filter match failed: %s", err.Error())
}
if match {
t.Logf("False positive match, should be 1 in 2**%d!", P)
}
match, err = filter2.Match(key, []byte("Nates"))
if err != nil {
t.Fatalf("Filter match failed: %s", err.Error())
}
if match {
t.Logf("False positive match, should be 1 in 2**%d!", P)
}
match, err = filter.Match(key, []byte("Quentins"))
if err != nil {
t.Fatalf("Filter match failed: %s", err.Error())
}
if match {
t.Logf("False positive match, should be 1 in 2**%d!", P)
}
match, err = filter2.Match(key, []byte("Quentins"))
if err != nil {
t.Fatalf("Filter match failed: %s", err.Error())
}
if match {
t.Logf("False positive match, should be 1 in 2**%d!", P)
}
}
// TestGCSFilterMatchAny checks that both the built and copied filters match a
// list correctly, logging any false positives without failing on them.
func TestGCSFilterMatchAny(t *testing.T) {
match, err := filter.MatchAny(key, contents2)
if err != nil {
t.Fatalf("Filter match any failed: %s", err.Error())
}
if match {
t.Logf("False positive match, should be 1 in 2**%d!", P)
}
match, err = filter2.MatchAny(key, contents2)
if err != nil {
t.Fatalf("Filter match any failed: %s", err.Error())
}
if match {
t.Logf("False positive match, should be 1 in 2**%d!", P)
}
contents2 = append(contents2, []byte("Nate"))
match, err = filter.MatchAny(key, contents2)
if err != nil {
t.Fatalf("Filter match any failed: %s", err.Error())
}
if !match {
t.Fatal("Filter didn't match any when it should have!")
}
match, err = filter2.MatchAny(key, contents2)
if err != nil {
t.Fatalf("Filter match any failed: %s", err.Error())
}
if !match {
t.Fatal("Filter didn't match any when it should have!")
}
}