From 5d4239de05b6901b8b658c96337c33284d2a1648 Mon Sep 17 00:00:00 2001 From: Edvard Date: Tue, 11 Dec 2018 13:47:04 +0100 Subject: [PATCH] Finish watcher and watcher tests (+fmt) --- libraries/shared/watcher.go | 5 +- libraries/shared/watcher_test.go | 109 ++++++++++++++---- pkg/transformers/shared/log_chunker.go | 4 +- pkg/transformers/shared/log_chunker_test.go | 4 +- pkg/transformers/shared/log_fetcher_test.go | 7 -- .../test_data/mocks/log_fetcher.go | 2 + .../mocks/mock_watcher_repository.go | 53 +++++++++ 7 files changed, 149 insertions(+), 35 deletions(-) create mode 100644 pkg/transformers/test_data/mocks/mock_watcher_repository.go diff --git a/libraries/shared/watcher.go b/libraries/shared/watcher.go index a9f94d91..77f06112 100644 --- a/libraries/shared/watcher.go +++ b/libraries/shared/watcher.go @@ -5,7 +5,6 @@ import ( "github.com/ethereum/go-ethereum/log" "github.com/vulcanize/vulcanizedb/pkg/core" "github.com/vulcanize/vulcanizedb/pkg/datastore/postgres" - "github.com/vulcanize/vulcanizedb/pkg/transformers" "github.com/vulcanize/vulcanizedb/pkg/transformers/shared" ) @@ -25,8 +24,8 @@ type Watcher struct { Repository WatcherRepository } -func NewWatcher(db *postgres.DB, fetcher shared.LogFetcher, repository WatcherRepository) Watcher { - transformerConfigs := transformers.TransformerConfigs() +func NewWatcher(db *postgres.DB, fetcher shared.LogFetcher, repository WatcherRepository, + transformerConfigs []shared.TransformerConfig) Watcher { var contractAddresses []common.Address var topic0s []common.Hash diff --git a/libraries/shared/watcher_test.go b/libraries/shared/watcher_test.go index 6f6634f8..0b32fcfe 100644 --- a/libraries/shared/watcher_test.go +++ b/libraries/shared/watcher_test.go @@ -2,6 +2,7 @@ package shared_test import ( "errors" + "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/core/types" . "github.com/onsi/ginkgo" . "github.com/onsi/gomega" @@ -10,6 +11,7 @@ import ( "github.com/vulcanize/vulcanizedb/pkg/datastore/postgres" "github.com/vulcanize/vulcanizedb/pkg/datastore/postgres/repositories" "github.com/vulcanize/vulcanizedb/pkg/fakes" + "github.com/vulcanize/vulcanizedb/pkg/transformers" shared2 "github.com/vulcanize/vulcanizedb/pkg/transformers/shared" "github.com/vulcanize/vulcanizedb/pkg/transformers/test_data/mocks" "github.com/vulcanize/vulcanizedb/test_config" @@ -42,7 +44,28 @@ func fakeTransformerInitializer(db *postgres.DB) shared2.Transformer { var _ = Describe("Watcher", func() { It("initialises correctly", func() { - // TODO Test watcher initialisation + db := test_config.NewTestDB(core.Node{ID: "testNode"}) + fetcher := mocks.MockLogFetcher{} + repository := &mocks.MockWatcherRepository{} + configA := shared2.TransformerConfig{ + ContractAddresses: []string{"0xA"}, + Topic: "0xA", + } + configB := shared2.TransformerConfig{ + ContractAddresses: []string{"0xB"}, + Topic: "0xB", + } + configs := []shared2.TransformerConfig{configA, configB} + watcher := shared.NewWatcher(db, &fetcher, repository, configs) + + Expect(watcher.DB).To(Equal(db)) + Expect(watcher.Fetcher).NotTo(BeNil()) + Expect(watcher.Chunker).NotTo(BeNil()) + Expect(watcher.Repository).To(Equal(repository)) + Expect(watcher.Topics).To(And( + ContainElement(common.HexToHash("0xA")), ContainElement(common.HexToHash("0xB")))) + Expect(watcher.Addresses).To(And( + ContainElement(common.HexToAddress("0xA")), ContainElement(common.HexToAddress("0xB")))) }) It("adds transformers", func() { @@ -69,22 +92,26 @@ var _ = Describe("Watcher", func() { watcher shared.Watcher fakeTransformer *MockTransformer headerRepository repositories.HeaderRepository - mockFetcher shared2.LogFetcher + mockFetcher mocks.MockLogFetcher + repository mocks.MockWatcherRepository ) BeforeEach(func() { db = test_config.NewTestDB(test_config.NewTestNode()) test_config.CleanTestDB(db) - mockFetcher = &mocks.MockLogFetcher{} - watcher = shared.NewWatcher(db, mockFetcher) + mockFetcher = mocks.MockLogFetcher{} headerRepository = repositories.NewHeaderRepository(db) _, err := headerRepository.CreateOrUpdateHeader(fakes.FakeHeader) Expect(err).NotTo(HaveOccurred()) + + repository = mocks.MockWatcherRepository{} + watcher = shared.NewWatcher(db, &mockFetcher, &repository, transformers.TransformerConfigs()) }) It("executes each transformer", func() { fakeTransformer = &MockTransformer{} watcher.Transformers = []shared2.Transformer{fakeTransformer} + repository.SetMissingHeaders([]core.Header{fakes.FakeHeader}) err := watcher.Execute() @@ -95,6 +122,7 @@ var _ = Describe("Watcher", func() { It("returns an error if transformer returns an error", func() { fakeTransformer = &MockTransformer{executeError: errors.New("Something bad happened")} watcher.Transformers = []shared2.Transformer{fakeTransformer} + repository.SetMissingHeaders([]core.Header{fakes.FakeHeader}) err := watcher.Execute() @@ -102,24 +130,65 @@ var _ = Describe("Watcher", func() { Expect(fakeTransformer.executeWasCalled).To(BeFalse()) }) - It("calls MissingHeaders", func() { - // TODO Tests for calling MissingHeaders - }) - - It("returns an error if missingHeaders returns an error", func() { - // TODO Test for propagating missingHeaders error - }) - - It("calls the log fetcher", func() { - // TODO Test for calling FetchLogs - }) - - It("returns an error if the log fetcher returns an error", func() { - // TODO Test for propagating log fetcher error - }) - It("passes only relevant logs to each transformer", func() { // TODO Test log delegation }) + + Describe("uses the repository correctly:", func() { + + It("calls MissingHeaders", func() { + err := watcher.Execute() + Expect(err).To(Not(HaveOccurred())) + Expect(repository.MissingHeadersCalled).To(BeTrue()) + }) + + It("propagates MissingHeaders errors", func() { + missingHeadersError := errors.New("MissingHeadersError") + repository.MissingHeadersError = missingHeadersError + + err := watcher.Execute() + Expect(err).To(MatchError(missingHeadersError)) + }) + + It("calls CreateNotCheckedSQL", func() { + err := watcher.Execute() + Expect(err).NotTo(HaveOccurred()) + Expect(repository.CreateNotCheckedSQLCalled).To(BeTrue()) + }) + + It("calls GetCheckedColumnNames", func() { + err := watcher.Execute() + Expect(err).NotTo(HaveOccurred()) + Expect(repository.GetCheckedColumnNamesCalled).To(BeTrue()) + }) + + It("propagates GetCheckedColumnNames errors", func() { + getCheckedColumnNamesError := errors.New("GetCheckedColumnNamesError") + repository.GetCheckedColumnNamesError = getCheckedColumnNamesError + + err := watcher.Execute() + Expect(err).To(MatchError(getCheckedColumnNamesError)) + }) + }) + + Describe("uses the LogFetcher correctly:", func() { + BeforeEach(func() { + repository.SetMissingHeaders([]core.Header{fakes.FakeHeader}) + }) + + It("fetches logs", func() { + err := watcher.Execute() + Expect(err).NotTo(HaveOccurred()) + Expect(mockFetcher.FetchLogsCalled).To(BeTrue()) + }) + + It("propagates log fetcher errors", func() { + fetcherError := errors.New("FetcherError") + mockFetcher.SetFetcherError(fetcherError) + + err := watcher.Execute() + Expect(err).To(MatchError(fetcherError)) + }) + }) }) }) diff --git a/pkg/transformers/shared/log_chunker.go b/pkg/transformers/shared/log_chunker.go index b6feb866..aede460a 100644 --- a/pkg/transformers/shared/log_chunker.go +++ b/pkg/transformers/shared/log_chunker.go @@ -19,8 +19,6 @@ import ( "github.com/ethereum/go-ethereum/core/types" ) -// TODO Add unit tests for LogChunker - type LogChunker struct { AddressToNames map[string][]string NameToTopic0 map[string]common.Hash @@ -40,7 +38,7 @@ func NewLogChunker(transformerConfigs []TransformerConfig) LogChunker { return LogChunker{ AddressToNames: addressToNames, - NameToTopic0: nameToTopic0, + NameToTopic0: nameToTopic0, } } diff --git a/pkg/transformers/shared/log_chunker_test.go b/pkg/transformers/shared/log_chunker_test.go index 96c1cf96..e657d1b4 100644 --- a/pkg/transformers/shared/log_chunker_test.go +++ b/pkg/transformers/shared/log_chunker_test.go @@ -71,7 +71,7 @@ var _ = Describe("Log chunker", func() { logs := []types.Log{log1, log2, log3, log4, log5} chunks := chunker.ChunkLogs(logs) - Expect(chunks["TransformerA"]).To(And(ContainElement(log1),ContainElement(log4))) + Expect(chunks["TransformerA"]).To(And(ContainElement(log1), ContainElement(log4))) Expect(chunks["TransformerB"]).To(BeEmpty()) Expect(chunks["TransformerC"]).To(ContainElement(log5)) }) @@ -119,4 +119,4 @@ var ( common.HexToHash("0xLogTopic5"), }, } -) \ No newline at end of file +) diff --git a/pkg/transformers/shared/log_fetcher_test.go b/pkg/transformers/shared/log_fetcher_test.go index 73deb656..4a0c55fa 100644 --- a/pkg/transformers/shared/log_fetcher_test.go +++ b/pkg/transformers/shared/log_fetcher_test.go @@ -26,14 +26,7 @@ import ( ) var _ = Describe("Fetcher", func() { - Describe("Iinitialisation", func() { - It("creates correct lookup maps", func() { - - }) - }) - Describe("FetchLogs", func() { - // TODO Add tests for aggregate fetching It("fetches logs based on the given query", func() { blockChain := fakes.NewMockBlockChain() fetcher := shared.NewFetcher(blockChain) diff --git a/pkg/transformers/test_data/mocks/log_fetcher.go b/pkg/transformers/test_data/mocks/log_fetcher.go index 1eeee33e..ff3db503 100644 --- a/pkg/transformers/test_data/mocks/log_fetcher.go +++ b/pkg/transformers/test_data/mocks/log_fetcher.go @@ -27,12 +27,14 @@ type MockLogFetcher struct { fetcherError error FetchedLogs []types.Log SetBcCalled bool + FetchLogsCalled bool } func (mlf *MockLogFetcher) FetchLogs(contractAddresses []common.Address, topics []common.Hash, header core.Header) ([]types.Log, error) { mlf.FetchedContractAddresses = append(mlf.FetchedContractAddresses, contractAddresses) mlf.FetchedTopics = [][]common.Hash{topics} mlf.FetchedBlocks = append(mlf.FetchedBlocks, header.BlockNumber) + mlf.FetchLogsCalled = true return mlf.FetchedLogs, mlf.fetcherError } diff --git a/pkg/transformers/test_data/mocks/mock_watcher_repository.go b/pkg/transformers/test_data/mocks/mock_watcher_repository.go new file mode 100644 index 00000000..323fdddf --- /dev/null +++ b/pkg/transformers/test_data/mocks/mock_watcher_repository.go @@ -0,0 +1,53 @@ +package mocks + +import ( + "github.com/vulcanize/vulcanizedb/pkg/core" + "github.com/vulcanize/vulcanizedb/pkg/datastore/postgres" +) + +type MockWatcherRepository struct { + ReturnCheckedColumnNames []string + GetCheckedColumnNamesError error + GetCheckedColumnNamesCalled bool + + ReturnNotCheckedSQL string + CreateNotCheckedSQLCalled bool + + ReturnMissingHeaders []core.Header + MissingHeadersError error + MissingHeadersCalled bool +} + +func (repository *MockWatcherRepository) GetCheckedColumnNames(db *postgres.DB) ([]string, error) { + repository.GetCheckedColumnNamesCalled = true + if repository.GetCheckedColumnNamesError != nil { + return []string{}, repository.GetCheckedColumnNamesError + } + + return repository.ReturnCheckedColumnNames, nil +} + +func (repository *MockWatcherRepository) SetCheckedColumnNames(checkedColumnNames []string) { + repository.ReturnCheckedColumnNames = checkedColumnNames +} + +func (repository *MockWatcherRepository) CreateNotCheckedSQL(boolColumns []string) string { + repository.CreateNotCheckedSQLCalled = true + return repository.ReturnNotCheckedSQL +} + +func (repository *MockWatcherRepository) SetNotCheckedSQL(notCheckedSql string) { + repository.ReturnNotCheckedSQL = notCheckedSql +} + +func (repository *MockWatcherRepository) MissingHeaders(startingBlockNumber int64, endingBlockNumber int64, db *postgres.DB, notCheckedSQL string) ([]core.Header, error) { + if repository.MissingHeadersError != nil { + return []core.Header{}, repository.MissingHeadersError + } + repository.MissingHeadersCalled = true + return repository.ReturnMissingHeaders, nil +} + +func (repository *MockWatcherRepository) SetMissingHeaders(headers []core.Header) { + repository.ReturnMissingHeaders = headers +}