diff --git a/pkg/transformers/shared/constants/checked_headers.go b/pkg/transformers/shared/constants/checked_headers.go index b3cea78b..91ddd6fb 100644 --- a/pkg/transformers/shared/constants/checked_headers.go +++ b/pkg/transformers/shared/constants/checked_headers.go @@ -16,4 +16,8 @@ var ( PitFileStabilityFeeChecked = "pit_file_stability_fee_checked" PriceFeedsChecked = "price_feeds_checked" TendChecked = "tend_checked" + VatFluxChecked = "vat_flux_checked" + VatFoldChecked = "vat_fold_checked" + VatGrabChecked = "vat_grab_checked" + VatHealChecked = "vat_heal_checked" ) diff --git a/pkg/transformers/vat_flux/repository.go b/pkg/transformers/vat_flux/repository.go index 5486bb56..af77d2ae 100644 --- a/pkg/transformers/vat_flux/repository.go +++ b/pkg/transformers/vat_flux/repository.go @@ -18,6 +18,8 @@ import ( "fmt" "github.com/vulcanize/vulcanizedb/pkg/core" "github.com/vulcanize/vulcanizedb/pkg/datastore/postgres" + "github.com/vulcanize/vulcanizedb/pkg/transformers/shared" + "github.com/vulcanize/vulcanizedb/pkg/transformers/shared/constants" ) type VatFluxRepository struct { @@ -46,10 +48,7 @@ func (repository VatFluxRepository) Create(headerId int64, models []interface{}) } } - _, err = tx.Exec(`INSERT INTO public.checked_headers (header_id, vat_flux_checked) - VALUES($1, $2) - ON CONFLICT (header_id) DO - UPDATE SET vat_flux_checked = $2`, headerId, true) + err = shared.MarkHeaderCheckedInTransaction(headerId, tx, constants.VatFluxChecked) if err != nil { tx.Rollback() return err @@ -59,26 +58,11 @@ func (repository VatFluxRepository) Create(headerId int64, models []interface{}) } func (repository VatFluxRepository) MarkHeaderChecked(headerId int64) error { - _, err := repository.db.Exec(`INSERT INTO public.checked_headers (header_id, vat_flux_checked) - VALUES($1, $2) - ON CONFLICT (header_id) DO - UPDATE SET vat_flux_checked = $2`, headerId, true) - - return err + return shared.MarkHeaderChecked(headerId, repository.db, constants.VatFluxChecked) } func (repository VatFluxRepository) MissingHeaders(startingBlock, endingBlock int64) ([]core.Header, error) { - var headers []core.Header - err := repository.db.Select(&headers, - `SELECT headers.id, block_number from headers - LEFT JOIN checked_headers on headers.id = header_id - WHERE (header_id ISNULL OR vat_flux_checked IS FALSE) - AND headers.block_number >= $1 - AND headers.block_number <= $2 - AND headers.eth_node_fingerprint = $3`, - startingBlock, endingBlock, repository.db.Node.ID) - - return headers, err + return shared.MissingHeaders(startingBlock, endingBlock, repository.db, constants.VatFluxChecked) } func (repository *VatFluxRepository) SetDB(db *postgres.DB) { diff --git a/pkg/transformers/vat_flux/repository_test.go b/pkg/transformers/vat_flux/repository_test.go index 86933bea..0289b59b 100644 --- a/pkg/transformers/vat_flux/repository_test.go +++ b/pkg/transformers/vat_flux/repository_test.go @@ -15,27 +15,23 @@ package vat_flux_test import ( - "math/rand" - . "github.com/onsi/ginkgo" . "github.com/onsi/gomega" - "github.com/vulcanize/vulcanizedb/pkg/core" "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/test_data" + "github.com/vulcanize/vulcanizedb/pkg/transformers/test_data/shared_behaviors" "github.com/vulcanize/vulcanizedb/pkg/transformers/vat_flux" "github.com/vulcanize/vulcanizedb/test_config" + "github.com/vulcanize/vulcanizedb/pkg/transformers/shared/constants" ) var _ = Describe("VatFlux Repository", func() { var ( - db *postgres.DB - repository vat_flux.VatFluxRepository - headerRepository repositories.HeaderRepository - headerId int64 - err error + db *postgres.DB + repository vat_flux.VatFluxRepository ) BeforeEach(func() { @@ -44,9 +40,6 @@ var _ = Describe("VatFlux Repository", func() { test_config.CleanTestDB(db) repository = vat_flux.VatFluxRepository{} repository.SetDB(db) - headerRepository = repositories.NewHeaderRepository(db) - headerId, err = headerRepository.CreateOrUpdateHeader(fakes.FakeHeader) - Expect(err).NotTo(HaveOccurred()) }) type VatFluxDBResult struct { @@ -55,12 +48,24 @@ var _ = Describe("VatFlux Repository", func() { HeaderId int64 `db:"header_id"` } - type CheckedHeaderResult struct { - VatFluxChecked bool `db:"vat_flux_checked"` - } - Describe("Create", func() { + vatFluxWithDifferentLogIdx := test_data.VatFluxModel + vatFluxWithDifferentLogIdx.LogIndex++ + inputs := shared_behaviors.CreateBehaviorInputs{ + CheckedHeaderColumnName: constants.VatFluxChecked, + LogEventTableName: "maker.vat_flux", + TestModel: test_data.VatFluxModel, + ModelWithDifferentLogIdx: vatFluxWithDifferentLogIdx, + Repository: &repository, + } + + shared_behaviors.SharedRepositoryCreateBehaviors(&inputs) + It("persists vat flux records", func() { + headerRepository := repositories.NewHeaderRepository(db) + headerId, err := headerRepository.CreateOrUpdateHeader(fakes.FakeHeader) + Expect(err).NotTo(HaveOccurred()) + anotherVatFlux := test_data.VatFluxModel anotherVatFlux.TransactionIndex = test_data.VatFluxModel.TransactionIndex + 1 err = repository.Create(headerId, []interface{}{test_data.VatFluxModel, anotherVatFlux}) @@ -79,175 +84,23 @@ var _ = Describe("VatFlux Repository", func() { Expect(dbResult[0].Raw).To(MatchJSON(test_data.VatFluxModel.Raw)) Expect(dbResult[0].HeaderId).To(Equal(headerId)) }) - - It("returns an error if the insertion fails", func() { - err = repository.Create(headerId, []interface{}{test_data.VatFluxModel}) - Expect(err).NotTo(HaveOccurred()) - - err = repository.Create(headerId, []interface{}{test_data.VatFluxModel}) - - Expect(err).To(HaveOccurred()) - Expect(err.Error()).To(ContainSubstring("pq: duplicate key value violates unique constraint")) - }) - - It("allows for multiple vat flux events in one transaction if they have different log indexes", func() { - err = repository.Create(headerId, []interface{}{test_data.VatFluxModel}) - Expect(err).NotTo(HaveOccurred()) - - anotherVatFlux := test_data.VatFluxModel - anotherVatFlux.LogIndex = anotherVatFlux.LogIndex + 1 - err = repository.Create(headerId, []interface{}{anotherVatFlux}) - - Expect(err).NotTo(HaveOccurred()) - }) - - It("marks the header as checked for vat flux logs", func() { - err = repository.Create(headerId, []interface{}{test_data.VatFluxModel}) - - Expect(err).NotTo(HaveOccurred()) - var headerChecked bool - err = db.Get(&headerChecked, `SELECT vat_flux_checked FROM public.checked_headers WHERE header_id = $1`, headerId) - Expect(err).NotTo(HaveOccurred()) - Expect(headerChecked).To(BeTrue()) - }) - - It("updates the header to checked if checked headers row already exists", func() { - _, err := db.Exec(`INSERT INTO public.checked_headers (header_id) VALUES ($1)`, headerId) - Expect(err).NotTo(HaveOccurred()) - - err = repository.Create(headerId, []interface{}{test_data.VatFluxModel}) - - Expect(err).NotTo(HaveOccurred()) - var headerChecked bool - err = db.Get(&headerChecked, `SELECT vat_flux_checked FROM public.checked_headers WHERE header_id = $1`, headerId) - Expect(err).NotTo(HaveOccurred()) - Expect(headerChecked).To(BeTrue()) - }) - - It("removes vat flux if corresponding header is deleted", func() { - err = repository.Create(headerId, []interface{}{test_data.VatFluxModel}) - Expect(err).NotTo(HaveOccurred()) - - _, err = db.Exec(`DELETE FROM headers WHERE id = $1`, headerId) - - Expect(err).NotTo(HaveOccurred()) - var count int - err = db.QueryRow(`SELECT count(*) from maker.vat_flux`).Scan(&count) - Expect(err).NotTo(HaveOccurred()) - Expect(count).To(Equal(0)) - }) - - It("wraps create in a transaction", func() { - err = repository.Create(headerId, []interface{}{test_data.VatFluxModel, test_data.VatFluxModel}) - - Expect(err).To(HaveOccurred()) - var count int - err = db.QueryRowx(`SELECT count(*) FROM maker.vat_flux`).Scan(&count) - Expect(count).To(Equal(0)) - }) - - It("returns an error if model is of wrong type", func() { - err = repository.Create(headerId, []interface{}{test_data.WrongModel{}}) - - Expect(err).To(HaveOccurred()) - Expect(err.Error()).To(ContainSubstring("model of type")) - }) }) Describe("MissingHeaders", func() { - var ( - startingBlock, vatFluxBlock, endingBlock, outsideRangeBlock int64 - headerIds, blockNumbers []int64 - ) + inputs := shared_behaviors.MissingHeadersBehaviorInputs{ + Repository: &repository, + RepositoryTwo: &vat_flux.VatFluxRepository{}, + } - BeforeEach(func() { - startingBlock = rand.Int63() - vatFluxBlock = startingBlock + 1 - endingBlock = startingBlock + 2 - outsideRangeBlock = startingBlock + 3 - - blockNumbers = []int64{startingBlock, vatFluxBlock, endingBlock, outsideRangeBlock} - headerIds = []int64{} - for _, n := range blockNumbers { - headerId, err := headerRepository.CreateOrUpdateHeader(fakes.GetFakeHeader(n)) - Expect(err).NotTo(HaveOccurred()) - headerIds = append(headerIds, headerId) - } - }) - - It("returns headers that haven't been checked", func() { - err = repository.MarkHeaderChecked(headerIds[0]) - Expect(err).NotTo(HaveOccurred()) - - headers, err := repository.MissingHeaders(startingBlock, endingBlock) - Expect(err).NotTo(HaveOccurred()) - Expect(headers[0].Id).To(Or(Equal(headerIds[1]), Equal(headerIds[2]))) - Expect(headers[1].Id).To(Or(Equal(headerIds[1]), Equal(headerIds[2]))) - Expect(len(headers)).To(Equal(2)) - }) - - It("returns header ids when checked_headers.vat_flux is false", func() { - err = repository.MarkHeaderChecked(headerIds[0]) - _, err = db.Exec(`INSERT INTO checked_headers (header_id) VALUES ($1)`, headerIds[1]) - Expect(err).NotTo(HaveOccurred()) - - headers, err := repository.MissingHeaders(startingBlock, endingBlock) - Expect(err).NotTo(HaveOccurred()) - Expect(headers[0].Id).To(Or(Equal(headerIds[1]), Equal(headerIds[2]))) - Expect(headers[1].Id).To(Or(Equal(headerIds[1]), Equal(headerIds[2]))) - Expect(len(headers)).To(Equal(2)) - }) - - It("only returns header ids for the current node", func() { - db2 := test_config.NewTestDB(core.Node{ID: "second node"}) - headerRepository2 := repositories.NewHeaderRepository(db2) - repository2 := vat_flux.VatFluxRepository{} - repository2.SetDB(db2) - - for _, n := range blockNumbers { - _, err = headerRepository2.CreateOrUpdateHeader(fakes.GetFakeHeader(n)) - Expect(err).NotTo(HaveOccurred()) - } - - err = repository.MarkHeaderChecked(headerIds[0]) - Expect(err).NotTo(HaveOccurred()) - - nodeOneMissingHeaders, err := repository.MissingHeaders(startingBlock, endingBlock) - Expect(err).NotTo(HaveOccurred()) - Expect(len(nodeOneMissingHeaders)).To(Equal(2)) - - nodeTwoMissingHeaders, err := repository2.MissingHeaders(startingBlock, endingBlock) - Expect(err).NotTo(HaveOccurred()) - Expect(len(nodeTwoMissingHeaders)).To(Equal(3)) - }) + shared_behaviors.SharedRepositoryMissingHeadersBehaviors(&inputs) }) Describe("MarkHeaderChecked", func() { - It("creates a new checked_header record", func() { - err := repository.MarkHeaderChecked(headerId) - Expect(err).NotTo(HaveOccurred()) + inputs := shared_behaviors.MarkedHeaderCheckedBehaviorInputs{ + CheckedHeaderColumnName: constants.VatFluxChecked, + Repository: &repository, + } - var checkedHeaderResult = CheckedHeaderResult{} - err = db.Get(&checkedHeaderResult, `SELECT vat_flux_checked FROM checked_headers WHERE header_id = $1`, headerId) - Expect(err).NotTo(HaveOccurred()) - Expect(checkedHeaderResult.VatFluxChecked).To(BeTrue()) - }) - - It("updates an existing checked header", func() { - _, err := db.Exec(`INSERT INTO checked_headers (header_id) VALUES($1)`, headerId) - Expect(err).NotTo(HaveOccurred()) - - var checkedHeaderResult CheckedHeaderResult - err = db.Get(&checkedHeaderResult, `SELECT vat_flux_checked FROM checked_headers WHERE header_id = $1`, headerId) - Expect(err).NotTo(HaveOccurred()) - Expect(checkedHeaderResult.VatFluxChecked).To(BeFalse()) - - err = repository.MarkHeaderChecked(headerId) - Expect(err).NotTo(HaveOccurred()) - - err = db.Get(&checkedHeaderResult, `SELECT vat_flux_checked FROM checked_headers WHERE header_id = $1`, headerId) - Expect(err).NotTo(HaveOccurred()) - Expect(checkedHeaderResult.VatFluxChecked).To(BeTrue()) - }) + shared_behaviors.SharedRepositoryMarkHeaderCheckedBehaviors(&inputs) }) }) diff --git a/pkg/transformers/vat_fold/repository.go b/pkg/transformers/vat_fold/repository.go index c336ea13..bb14f172 100644 --- a/pkg/transformers/vat_fold/repository.go +++ b/pkg/transformers/vat_fold/repository.go @@ -19,6 +19,8 @@ import ( "github.com/vulcanize/vulcanizedb/pkg/core" "github.com/vulcanize/vulcanizedb/pkg/datastore/postgres" + "github.com/vulcanize/vulcanizedb/pkg/transformers/shared" + "github.com/vulcanize/vulcanizedb/pkg/transformers/shared/constants" ) type VatFoldRepository struct { @@ -47,13 +49,8 @@ func (repository VatFoldRepository) Create(headerID int64, models []interface{}) return err } } - _, err = tx.Exec( - `INSERT INTO public.checked_headers (header_id, vat_fold_checked) - VALUES($1, $2) - ON CONFLICT (header_id) DO - UPDATE SET vat_fold_checked = $2`, - headerID, true, - ) + + err = shared.MarkHeaderCheckedInTransaction(headerID, tx, constants.VatFoldChecked) if err != nil { tx.Rollback() return err @@ -63,31 +60,11 @@ func (repository VatFoldRepository) Create(headerID int64, models []interface{}) } func (repository VatFoldRepository) MarkHeaderChecked(headerID int64) error { - _, err := repository.db.Exec( - `INSERT INTO public.checked_headers (header_id, vat_fold_checked) - VALUES ($1, $2) - ON CONFLICT (header_id) DO - UPDATE SET vat_fold_checked = $2`, - headerID, true, - ) - return err + return shared.MarkHeaderChecked(headerID, repository.db, constants.VatFoldChecked) } func (repository VatFoldRepository) MissingHeaders(startingBlockNumber, endingBlockNumber int64) ([]core.Header, error) { - var result []core.Header - err := repository.db.Select( - &result, - `SELECT headers.id, headers.block_number FROM headers - LEFT JOIN checked_headers on headers.id = header_id - WHERE (header_id ISNULL OR vat_fold_checked IS FALSE) - AND headers.block_number >= $1 - AND headers.block_number <= $2 - AND headers.eth_node_fingerprint = $3`, - startingBlockNumber, - endingBlockNumber, - repository.db.Node.ID, - ) - return result, err + return shared.MissingHeaders(startingBlockNumber, endingBlockNumber, repository.db, constants.VatFoldChecked) } func (repository *VatFoldRepository) SetDB(db *postgres.DB) { diff --git a/pkg/transformers/vat_fold/repository_test.go b/pkg/transformers/vat_fold/repository_test.go index 863618f0..a26ff75b 100644 --- a/pkg/transformers/vat_fold/repository_test.go +++ b/pkg/transformers/vat_fold/repository_test.go @@ -15,27 +15,23 @@ package vat_fold_test import ( - "database/sql" - "math/rand" - . "github.com/onsi/ginkgo" . "github.com/onsi/gomega" - "github.com/vulcanize/vulcanizedb/pkg/core" "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/shared/constants" "github.com/vulcanize/vulcanizedb/pkg/transformers/test_data" + "github.com/vulcanize/vulcanizedb/pkg/transformers/test_data/shared_behaviors" "github.com/vulcanize/vulcanizedb/pkg/transformers/vat_fold" "github.com/vulcanize/vulcanizedb/test_config" ) var _ = Describe("Vat.fold repository", func() { var ( - db *postgres.DB - repository vat_fold.VatFoldRepository - headerRepository repositories.HeaderRepository - err error + db *postgres.DB + repository vat_fold.VatFoldRepository ) BeforeEach(func() { @@ -44,23 +40,31 @@ var _ = Describe("Vat.fold repository", func() { test_config.CleanTestDB(db) repository = vat_fold.VatFoldRepository{} repository.SetDB(db) - headerRepository = repositories.NewHeaderRepository(db) }) Describe("Create", func() { - var headerID int64 + modelWithDifferentLogIdx := test_data.VatFoldModel + modelWithDifferentLogIdx.LogIndex++ - BeforeEach(func() { - headerID, err = headerRepository.CreateOrUpdateHeader(fakes.FakeHeader) - Expect(err).NotTo(HaveOccurred()) - }) + inputs := shared_behaviors.CreateBehaviorInputs{ + CheckedHeaderColumnName: constants.VatFoldChecked, + LogEventTableName: "maker.vat_fold", + TestModel: test_data.VatFoldModel, + ModelWithDifferentLogIdx: modelWithDifferentLogIdx, + Repository: &repository, + } + + shared_behaviors.SharedRepositoryCreateBehaviors(&inputs) It("adds a vat fold event", func() { + headerRepository := repositories.NewHeaderRepository(db) + headerID, err := headerRepository.CreateOrUpdateHeader(fakes.FakeHeader) + Expect(err).NotTo(HaveOccurred()) err = repository.Create(headerID, []interface{}{test_data.VatFoldModel}) Expect(err).NotTo(HaveOccurred()) var dbVatFold vat_fold.VatFoldModel - err := db.Get(&dbVatFold, `SELECT ilk, urn, rate, log_idx, tx_idx, raw_log FROM maker.vat_fold WHERE header_id = $1`, headerID) + err = db.Get(&dbVatFold, `SELECT ilk, urn, rate, log_idx, tx_idx, raw_log FROM maker.vat_fold WHERE header_id = $1`, headerID) Expect(err).NotTo(HaveOccurred()) Expect(dbVatFold.Ilk).To(Equal(test_data.VatFoldModel.Ilk)) @@ -70,169 +74,23 @@ var _ = Describe("Vat.fold repository", func() { Expect(dbVatFold.TransactionIndex).To(Equal(test_data.VatFoldModel.TransactionIndex)) Expect(dbVatFold.Raw).To(MatchJSON(test_data.VatFoldModel.Raw)) }) - - It("marks header as checked for logs", func() { - err = repository.Create(headerID, []interface{}{test_data.VatFoldModel}) - - Expect(err).NotTo(HaveOccurred()) - var headerChecked bool - err = db.Get(&headerChecked, `SELECT vat_fold_checked FROM public.checked_headers WHERE header_id = $1`, headerID) - Expect(err).NotTo(HaveOccurred()) - Expect(headerChecked).To(BeTrue()) - }) - - It("updates the header to checked if checked headers row already exists", func() { - _, err = db.Exec(`INSERT INTO public.checked_headers (header_id) VALUES ($1)`, headerID) - Expect(err).NotTo(HaveOccurred()) - - err = repository.Create(headerID, []interface{}{test_data.VatFoldModel}) - - Expect(err).NotTo(HaveOccurred()) - var headerChecked bool - err = db.Get(&headerChecked, `SELECT vat_fold_checked FROM public.checked_headers WHERE header_id = $1`, headerID) - Expect(err).NotTo(HaveOccurred()) - Expect(headerChecked).To(BeTrue()) - }) - - It("does not duplicate vat fold events", func() { - err = repository.Create(headerID, []interface{}{test_data.VatFoldModel}) - Expect(err).NotTo(HaveOccurred()) - - err = repository.Create(headerID, []interface{}{test_data.VatFoldModel}) - - Expect(err).To(HaveOccurred()) - Expect(err.Error()).To(ContainSubstring("pq: duplicate key value violates unique constraint")) - }) - - It("removes vat fold if corresponding header is deleted", func() { - err = repository.Create(headerID, []interface{}{test_data.VatFoldModel}) - Expect(err).NotTo(HaveOccurred()) - - _, err = db.Exec(`DELETE FROM headers WHERE id = $1`, headerID) - - Expect(err).NotTo(HaveOccurred()) - var dbVatFold vat_fold.VatFoldModel - err = db.Get(&dbVatFold, `SELECT ilk, urn, rate, log_idx, tx_idx, raw_log FROM maker.vat_fold WHERE header_id = $1`, headerID) - Expect(err).To(HaveOccurred()) - Expect(err).To(MatchError(sql.ErrNoRows)) - }) - - It("returns an error if model is of wrong type", func() { - err = repository.Create(headerID, []interface{}{test_data.WrongModel{}}) - - Expect(err).To(HaveOccurred()) - Expect(err.Error()).To(ContainSubstring("model of type")) - }) }) Describe("MarkHeaderChecked", func() { - var headerID int64 - - BeforeEach(func() { - headerID, err = headerRepository.CreateOrUpdateHeader(fakes.FakeHeader) - Expect(err).NotTo(HaveOccurred()) - }) - - type CheckedHeaderResult struct { - VatFoldChecked bool `db:"vat_fold_checked"` + inputs := shared_behaviors.MarkedHeaderCheckedBehaviorInputs{ + CheckedHeaderColumnName: constants.VatFoldChecked, + Repository: &repository, } - It("creates a new checked header record", func() { - err := repository.MarkHeaderChecked(headerID) - Expect(err).NotTo(HaveOccurred()) - - var checkedHeaderResult = CheckedHeaderResult{} - err = db.Get(&checkedHeaderResult, `SELECT vat_fold_checked FROM checked_headers WHERE header_id = $1`, headerID) - Expect(err).NotTo(HaveOccurred()) - Expect(checkedHeaderResult.VatFoldChecked).To(BeTrue()) - }) - - It("updates an existing checked header", func() { - _, err := db.Exec(`INSERT INTO checked_headers (header_id) VALUES($1)`, headerID) - Expect(err).NotTo(HaveOccurred()) - - var checkedHeaderResult CheckedHeaderResult - err = db.Get(&checkedHeaderResult, `SELECT vat_fold_checked FROM checked_headers WHERE header_id = $1`, headerID) - Expect(err).NotTo(HaveOccurred()) - Expect(checkedHeaderResult.VatFoldChecked).To(BeFalse()) - - err = repository.MarkHeaderChecked(headerID) - Expect(err).NotTo(HaveOccurred()) - - err = db.Get(&checkedHeaderResult, `SELECT vat_fold_checked FROM checked_headers WHERE header_id = $1`, headerID) - Expect(err).NotTo(HaveOccurred()) - Expect(checkedHeaderResult.VatFoldChecked).To(BeTrue()) - }) + shared_behaviors.SharedRepositoryMarkHeaderCheckedBehaviors(&inputs) }) Describe("MissingHeaders", func() { - var ( - startingBlock, vatFoldBlock, endingBlock int64 - blockNumbers, headerIDs []int64 - ) + inputs := shared_behaviors.MissingHeadersBehaviorInputs{ + Repository: &repository, + RepositoryTwo: &vat_fold.VatFoldRepository{}, + } - BeforeEach(func() { - startingBlock = rand.Int63() - vatFoldBlock = startingBlock + 1 - endingBlock = startingBlock + 2 - - blockNumbers = []int64{startingBlock, vatFoldBlock, endingBlock, endingBlock + 1} - - headerIDs = []int64{} - for _, n := range blockNumbers { - headerID, err := headerRepository.CreateOrUpdateHeader(fakes.GetFakeHeader(n)) - Expect(err).NotTo(HaveOccurred()) - headerIDs = append(headerIDs, headerID) - } - }) - - It("returns headers that haven't been checked", func() { - err := repository.MarkHeaderChecked(headerIDs[1]) - Expect(err).NotTo(HaveOccurred()) - - headers, err := repository.MissingHeaders(startingBlock, endingBlock) - - Expect(err).NotTo(HaveOccurred()) - Expect(len(headers)).To(Equal(2)) - Expect(headers[0].BlockNumber).To(Or(Equal(startingBlock), Equal(endingBlock))) - Expect(headers[1].BlockNumber).To(Or(Equal(startingBlock), Equal(endingBlock))) - }) - - It("only treats headers as checked if vat fold logs have been checked", func() { - _, err := db.Exec(`INSERT INTO public.checked_headers (header_id) VALUES ($1)`, headerIDs[1]) - Expect(err).NotTo(HaveOccurred()) - - headers, err := repository.MissingHeaders(startingBlock, endingBlock) - - Expect(err).NotTo(HaveOccurred()) - Expect(len(headers)).To(Equal(3)) - Expect(headers[0].BlockNumber).To(Or(Equal(startingBlock), Equal(endingBlock), Equal(vatFoldBlock))) - Expect(headers[1].BlockNumber).To(Or(Equal(startingBlock), Equal(endingBlock), Equal(vatFoldBlock))) - Expect(headers[2].BlockNumber).To(Or(Equal(startingBlock), Equal(endingBlock), Equal(vatFoldBlock))) - }) - - It("only returns headers associated with the current node", func() { - dbTwo := test_config.NewTestDB(core.Node{ID: "second"}) - headerRepositoryTwo := repositories.NewHeaderRepository(dbTwo) - - for _, n := range blockNumbers { - _, err = headerRepositoryTwo.CreateOrUpdateHeader(fakes.GetFakeHeader(n)) - Expect(err).NotTo(HaveOccurred()) - } - - repositoryTwo := vat_fold.VatFoldRepository{} - repositoryTwo.SetDB(dbTwo) - - err := repository.MarkHeaderChecked(headerIDs[0]) - Expect(err).NotTo(HaveOccurred()) - - nodeOneMissingHeaders, err := repository.MissingHeaders(blockNumbers[0], blockNumbers[len(blockNumbers)-1]) - Expect(err).NotTo(HaveOccurred()) - Expect(len(nodeOneMissingHeaders)).To(Equal(len(blockNumbers) - 1)) - - nodeTwoMissingHeaders, err := repositoryTwo.MissingHeaders(blockNumbers[0], blockNumbers[len(blockNumbers)-1]) - Expect(err).NotTo(HaveOccurred()) - Expect(len(nodeTwoMissingHeaders)).To(Equal(len(blockNumbers))) - }) + shared_behaviors.SharedRepositoryMissingHeadersBehaviors(&inputs) }) }) diff --git a/pkg/transformers/vat_grab/repository.go b/pkg/transformers/vat_grab/repository.go index 7f261984..fe8e39a5 100644 --- a/pkg/transformers/vat_grab/repository.go +++ b/pkg/transformers/vat_grab/repository.go @@ -5,6 +5,8 @@ import ( "github.com/vulcanize/vulcanizedb/pkg/core" "github.com/vulcanize/vulcanizedb/pkg/datastore/postgres" + "github.com/vulcanize/vulcanizedb/pkg/transformers/shared" + "github.com/vulcanize/vulcanizedb/pkg/transformers/shared/constants" ) type VatGrabRepository struct { @@ -32,10 +34,7 @@ func (repository VatGrabRepository) Create(headerID int64, models []interface{}) return err } } - _, err = tx.Exec(`INSERT INTO public.checked_headers (header_id, vat_grab_checked) - VALUES ($1, $2) - ON CONFLICT (header_id) DO - UPDATE SET vat_grab_checked = $2`, headerID, true) + err = shared.MarkHeaderCheckedInTransaction(headerID, tx, constants.VatGrabChecked) if err != nil { tx.Rollback() return err @@ -44,28 +43,11 @@ func (repository VatGrabRepository) Create(headerID int64, models []interface{}) } func (repository VatGrabRepository) MarkHeaderChecked(headerID int64) error { - _, err := repository.db.Exec(`INSERT INTO public.checked_headers (header_id, vat_grab_checked) - VALUES ($1, $2) - ON CONFLICT (header_id) DO - UPDATE SET vat_grab_checked = $2`, headerID, true) - return err + return shared.MarkHeaderChecked(headerID, repository.db, constants.VatGrabChecked) } func (repository VatGrabRepository) MissingHeaders(startingBlockNumber, endingBlockNumber int64) ([]core.Header, error) { - var result []core.Header - err := repository.db.Select( - &result, - `SELECT headers.id, headers.block_number FROM headers - LEFT JOIN checked_headers on headers.id = header_id - WHERE (header_id ISNULL OR vat_grab_checked IS FALSE) - AND headers.block_number >= $1 - AND headers.block_number <= $2 - AND headers.eth_node_fingerprint = $3`, - startingBlockNumber, - endingBlockNumber, - repository.db.Node.ID, - ) - return result, err + return shared.MissingHeaders(startingBlockNumber, endingBlockNumber, repository.db, constants.VatGrabChecked) } func (repository *VatGrabRepository) SetDB(db *postgres.DB) { diff --git a/pkg/transformers/vat_grab/repository_test.go b/pkg/transformers/vat_grab/repository_test.go index 2d563c26..1d6e222c 100644 --- a/pkg/transformers/vat_grab/repository_test.go +++ b/pkg/transformers/vat_grab/repository_test.go @@ -1,17 +1,16 @@ package vat_grab_test import ( - "database/sql" . "github.com/onsi/ginkgo" . "github.com/onsi/gomega" - "github.com/vulcanize/vulcanizedb/pkg/core" "github.com/vulcanize/vulcanizedb/pkg/datastore" "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/factories" + "github.com/vulcanize/vulcanizedb/pkg/transformers/shared/constants" "github.com/vulcanize/vulcanizedb/pkg/transformers/test_data" + "github.com/vulcanize/vulcanizedb/pkg/transformers/test_data/shared_behaviors" "github.com/vulcanize/vulcanizedb/pkg/transformers/vat_grab" "github.com/vulcanize/vulcanizedb/test_config" ) @@ -19,30 +18,37 @@ import ( var _ = Describe("Vat grab repository", func() { var ( db *postgres.DB - vatGrabRepository factories.Repository - err error + vatGrabRepository vat_grab.VatGrabRepository headerRepository datastore.HeaderRepository ) BeforeEach(func() { - db = test_config.NewTestDB(core.Node{}) + db = test_config.NewTestDB(test_config.NewTestNode()) test_config.CleanTestDB(db) headerRepository = repositories.NewHeaderRepository(db) - vatGrabRepository = &vat_grab.VatGrabRepository{} + vatGrabRepository = vat_grab.VatGrabRepository{} vatGrabRepository.SetDB(db) }) Describe("Create", func() { - var headerID int64 + modelWithDifferentLogIdx := test_data.VatGrabModel + modelWithDifferentLogIdx.LogIndex++ - BeforeEach(func() { - headerID, err = headerRepository.CreateOrUpdateHeader(fakes.FakeHeader) - Expect(err).NotTo(HaveOccurred()) - }) + inputs := shared_behaviors.CreateBehaviorInputs{ + CheckedHeaderColumnName: constants.VatGrabChecked, + LogEventTableName: "maker.vat_grab", + TestModel: test_data.VatGrabModel, + ModelWithDifferentLogIdx: modelWithDifferentLogIdx, + Repository: &vatGrabRepository, + } + + shared_behaviors.SharedRepositoryCreateBehaviors(&inputs) It("adds a vat grab event", func() { - err = vatGrabRepository.Create(headerID, []interface{}{test_data.VatGrabModel}) + headerID, err := headerRepository.CreateOrUpdateHeader(fakes.FakeHeader) + Expect(err).NotTo(HaveOccurred()) + err = vatGrabRepository.Create(headerID, []interface{}{test_data.VatGrabModel}) Expect(err).NotTo(HaveOccurred()) var dbVatGrab vat_grab.VatGrabModel err = db.Get(&dbVatGrab, `SELECT ilk, urn, v, w, dink, dart, log_idx, tx_idx, raw_log FROM maker.vat_grab WHERE header_id = $1`, headerID) @@ -57,157 +63,23 @@ var _ = Describe("Vat grab repository", func() { Expect(dbVatGrab.TransactionIndex).To(Equal(test_data.VatGrabModel.TransactionIndex)) Expect(dbVatGrab.Raw).To(MatchJSON(test_data.VatGrabModel.Raw)) }) - - It("marks header as checked for logs", func() { - err = vatGrabRepository.Create(headerID, []interface{}{test_data.VatGrabModel}) - - Expect(err).NotTo(HaveOccurred()) - var headerChecked bool - err = db.Get(&headerChecked, `SELECT vat_grab_checked FROM public.checked_headers WHERE header_id = $1`, headerID) - Expect(err).NotTo(HaveOccurred()) - Expect(headerChecked).To(BeTrue()) - }) - - It("updates the header to checked if checked headers row already exists", func() { - _, err = db.Exec(`INSERT INTO public.checked_headers (header_id) VALUES ($1)`, headerID) - Expect(err).NotTo(HaveOccurred()) - - err = vatGrabRepository.Create(headerID, []interface{}{test_data.VatGrabModel}) - - Expect(err).NotTo(HaveOccurred()) - var headerChecked bool - err = db.Get(&headerChecked, `SELECT vat_grab_checked FROM public.checked_headers WHERE header_id = $1`, headerID) - Expect(err).NotTo(HaveOccurred()) - Expect(headerChecked).To(BeTrue()) - }) - - It("does not duplicate vat grab events", func() { - err = vatGrabRepository.Create(headerID, []interface{}{test_data.VatGrabModel}) - Expect(err).NotTo(HaveOccurred()) - - err = vatGrabRepository.Create(headerID, []interface{}{test_data.VatGrabModel}) - - Expect(err).To(HaveOccurred()) - Expect(err.Error()).To(ContainSubstring("pq: duplicate key value violates unique constraint")) - }) - - It("removes vat grab if corresponding header is deleted", func() { - err = vatGrabRepository.Create(headerID, []interface{}{test_data.VatGrabModel}) - Expect(err).NotTo(HaveOccurred()) - - _, err = db.Exec(`DELETE FROM headers WHERE id = $1`, headerID) - - Expect(err).NotTo(HaveOccurred()) - var dbVatGrab vat_grab.VatGrabModel - err = db.Get(&dbVatGrab, `SELECT ilk, urn, v, w, dink, dart, log_idx, tx_idx, raw_log FROM maker.vat_grab WHERE header_id = $1`, headerID) - Expect(err).To(HaveOccurred()) - Expect(err).To(MatchError(sql.ErrNoRows)) - }) - - It("returns an error if the wrong model is passed in", func() { - badModel := struct{}{} - err = vatGrabRepository.Create(headerID, []interface{}{badModel}) - - Expect(err).To(HaveOccurred()) - Expect(err.Error()).To(ContainSubstring("model of type struct {}, not vat_grab.VatGrabModel")) - }) }) Describe("MarkHeaderChecked", func() { - var headerID int64 + inputs := shared_behaviors.MarkedHeaderCheckedBehaviorInputs{ + CheckedHeaderColumnName: constants.VatGrabChecked, + Repository: &vatGrabRepository, + } - BeforeEach(func() { - headerID, err = headerRepository.CreateOrUpdateHeader(fakes.FakeHeader) - Expect(err).NotTo(HaveOccurred()) - }) - - It("creates a row for a new headerID", func() { - err = vatGrabRepository.MarkHeaderChecked(headerID) - - Expect(err).NotTo(HaveOccurred()) - var headerChecked bool - err = db.Get(&headerChecked, `SELECT vat_grab_checked FROM public.checked_headers WHERE header_id = $1`, headerID) - Expect(err).NotTo(HaveOccurred()) - Expect(headerChecked).To(BeTrue()) - }) - - It("updates row when headerID already exists", func() { - _, err = db.Exec(`INSERT INTO public.checked_headers (header_id) VALUES ($1)`, headerID) - err = vatGrabRepository.MarkHeaderChecked(headerID) - - Expect(err).NotTo(HaveOccurred()) - var headerChecked bool - err = db.Get(&headerChecked, `SELECT vat_grab_checked FROM public.checked_headers WHERE header_id = $1`, headerID) - Expect(err).NotTo(HaveOccurred()) - Expect(headerChecked).To(BeTrue()) - }) + shared_behaviors.SharedRepositoryMarkHeaderCheckedBehaviors(&inputs) }) Describe("MissingHeaders", func() { - var ( - startingBlock, vatGrabBlock, endingBlock int64 - blockNumbers, headerIDs []int64 - ) + inputs := shared_behaviors.MissingHeadersBehaviorInputs{ + Repository: &vatGrabRepository, + RepositoryTwo: &vat_grab.VatGrabRepository{}, + } - BeforeEach(func() { - startingBlock = GinkgoRandomSeed() - vatGrabBlock = startingBlock + 1 - endingBlock = startingBlock + 2 - - blockNumbers = []int64{startingBlock, vatGrabBlock, endingBlock, endingBlock + 1} - - headerIDs = []int64{} - for _, n := range blockNumbers { - headerID, err := headerRepository.CreateOrUpdateHeader(fakes.GetFakeHeader(n)) - Expect(err).NotTo(HaveOccurred()) - headerIDs = append(headerIDs, headerID) - } - }) - - It("returns headers that haven't been checked", func() { - err := vatGrabRepository.MarkHeaderChecked(headerIDs[1]) - Expect(err).NotTo(HaveOccurred()) - - headers, err := vatGrabRepository.MissingHeaders(startingBlock, endingBlock) - - Expect(err).NotTo(HaveOccurred()) - Expect(len(headers)).To(Equal(2)) - Expect(headers[0].BlockNumber).To(Or(Equal(startingBlock), Equal(endingBlock))) - Expect(headers[1].BlockNumber).To(Or(Equal(startingBlock), Equal(endingBlock))) - }) - - It("only treats headers as checked if vat grab logs have been checked", func() { - _, err := db.Exec(`INSERT INTO public.checked_headers (header_id) VALUES ($1)`, headerIDs[1]) - Expect(err).NotTo(HaveOccurred()) - - headers, err := vatGrabRepository.MissingHeaders(startingBlock, endingBlock) - - Expect(err).NotTo(HaveOccurred()) - Expect(len(headers)).To(Equal(3)) - Expect(headers[0].BlockNumber).To(Or(Equal(startingBlock), Equal(endingBlock), Equal(vatGrabBlock))) - Expect(headers[1].BlockNumber).To(Or(Equal(startingBlock), Equal(endingBlock), Equal(vatGrabBlock))) - Expect(headers[2].BlockNumber).To(Or(Equal(startingBlock), Equal(endingBlock), Equal(vatGrabBlock))) - }) - - It("only returns headers associated with the current node", func() { - dbTwo := test_config.NewTestDB(core.Node{ID: "second"}) - headerRepositoryTwo := repositories.NewHeaderRepository(dbTwo) - for _, n := range blockNumbers { - _, err = headerRepositoryTwo.CreateOrUpdateHeader(fakes.GetFakeHeader(n)) - Expect(err).NotTo(HaveOccurred()) - } - vatGrabRepositoryTwo := vat_grab.VatGrabRepository{} - vatGrabRepositoryTwo.SetDB(dbTwo) - err := vatGrabRepository.MarkHeaderChecked(headerIDs[0]) - Expect(err).NotTo(HaveOccurred()) - - nodeOneMissingHeaders, err := vatGrabRepository.MissingHeaders(blockNumbers[0], blockNumbers[len(blockNumbers)-1]) - Expect(err).NotTo(HaveOccurred()) - Expect(len(nodeOneMissingHeaders)).To(Equal(len(blockNumbers) - 1)) - - nodeTwoMissingHeaders, err := vatGrabRepositoryTwo.MissingHeaders(blockNumbers[0], blockNumbers[len(blockNumbers)-1]) - Expect(err).NotTo(HaveOccurred()) - Expect(len(nodeTwoMissingHeaders)).To(Equal(len(blockNumbers))) - }) + shared_behaviors.SharedRepositoryMissingHeadersBehaviors(&inputs) }) }) diff --git a/pkg/transformers/vat_heal/repository.go b/pkg/transformers/vat_heal/repository.go index 5d4b8562..84d2a980 100644 --- a/pkg/transformers/vat_heal/repository.go +++ b/pkg/transformers/vat_heal/repository.go @@ -19,6 +19,8 @@ import ( "github.com/vulcanize/vulcanizedb/pkg/core" "github.com/vulcanize/vulcanizedb/pkg/datastore/postgres" + "github.com/vulcanize/vulcanizedb/pkg/transformers/shared" + "github.com/vulcanize/vulcanizedb/pkg/transformers/shared/constants" ) type VatHealRepository struct { @@ -50,10 +52,7 @@ func (repository VatHealRepository) Create(headerId int64, models []interface{}) } } - _, err = tx.Exec(`INSERT INTO public.checked_headers (header_id, vat_heal_checked) - VALUES($1, $2) - ON CONFLICT (header_id) DO - UPDATE SET vat_heal_checked = $2`, headerId, true) + err = shared.MarkHeaderCheckedInTransaction(headerId, tx, constants.VatHealChecked) if err != nil { tx.Rollback() return err @@ -62,24 +61,9 @@ func (repository VatHealRepository) Create(headerId int64, models []interface{}) } func (repository VatHealRepository) MissingHeaders(startingBlock, endingBlock int64) ([]core.Header, error) { - var headers []core.Header - err := repository.db.Select(&headers, - `SELECT headers.id, block_number from headers - LEFT JOIN checked_headers on headers.id = header_id - WHERE (header_id ISNULL OR vat_heal_checked IS FALSE) - AND headers.block_number >= $1 - AND headers.block_number <= $2 - AND headers.eth_node_fingerprint = $3`, - startingBlock, endingBlock, repository.db.Node.ID) - - return headers, err + return shared.MissingHeaders(startingBlock, endingBlock, repository.db, constants.VatHealChecked) } func (repository VatHealRepository) MarkHeaderChecked(headerId int64) error { - _, err := repository.db.Exec(`INSERT INTO public.checked_headers (header_id, vat_heal_checked) - VALUES($1, $2) - ON CONFLICT (header_id) DO - UPDATE SET vat_heal_checked = $2`, headerId, true) - - return err + return shared.MarkHeaderChecked(headerId, repository.db, constants.VatHealChecked) } diff --git a/pkg/transformers/vat_heal/repository_test.go b/pkg/transformers/vat_heal/repository_test.go index 7b4a3741..9cc668fc 100644 --- a/pkg/transformers/vat_heal/repository_test.go +++ b/pkg/transformers/vat_heal/repository_test.go @@ -15,26 +15,23 @@ package vat_heal_test import ( - "math/rand" - . "github.com/onsi/ginkgo" . "github.com/onsi/gomega" - "github.com/vulcanize/vulcanizedb/pkg/core" "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/shared/constants" "github.com/vulcanize/vulcanizedb/pkg/transformers/test_data" + "github.com/vulcanize/vulcanizedb/pkg/transformers/test_data/shared_behaviors" "github.com/vulcanize/vulcanizedb/pkg/transformers/vat_heal" "github.com/vulcanize/vulcanizedb/test_config" ) var _ = Describe("VatHeal Repository", func() { var ( - db *postgres.DB - repository vat_heal.VatHealRepository - headerRepository repositories.HeaderRepository - err error + db *postgres.DB + repository vat_heal.VatHealRepository ) BeforeEach(func() { @@ -42,7 +39,6 @@ var _ = Describe("VatHeal Repository", func() { test_config.CleanTestDB(db) repository = vat_heal.VatHealRepository{} repository.SetDB(db) - headerRepository = repositories.NewHeaderRepository(db) }) type VatHealDBResult struct { @@ -51,19 +47,23 @@ var _ = Describe("VatHeal Repository", func() { HeaderId int64 `db:"header_id"` } - type CheckedHeaderResult struct { - VatHealChecked bool `db:"vat_heal_checked"` - } - Describe("Create", func() { - var headerId int64 + modelWithDifferentLogIdx := test_data.VatHealModel + modelWithDifferentLogIdx.LogIndex++ + inputs := shared_behaviors.CreateBehaviorInputs{ + CheckedHeaderColumnName: constants.VatHealChecked, + LogEventTableName: "maker.vat_heal", + TestModel: test_data.VatHealModel, + ModelWithDifferentLogIdx: modelWithDifferentLogIdx, + Repository: &repository, + } - BeforeEach(func() { - headerId, err = headerRepository.CreateOrUpdateHeader(fakes.FakeHeader) - Expect(err).NotTo(HaveOccurred()) - }) + shared_behaviors.SharedRepositoryCreateBehaviors(&inputs) It("persists vat heal records", func() { + headerRepository := repositories.NewHeaderRepository(db) + headerId, err := headerRepository.CreateOrUpdateHeader(fakes.FakeHeader) + Expect(err).NotTo(HaveOccurred()) anotherVatHeal := test_data.VatHealModel anotherVatHeal.LogIndex = test_data.VatHealModel.LogIndex + 1 err = repository.Create(headerId, []interface{}{test_data.VatHealModel, anotherVatHeal}) @@ -81,171 +81,23 @@ var _ = Describe("VatHeal Repository", func() { Expect(dbResult[0].Raw).To(MatchJSON(test_data.VatHealModel.Raw)) Expect(dbResult[0].HeaderId).To(Equal(headerId)) }) - - It("returns an error if the insertion fails", func() { - err = repository.Create(headerId, []interface{}{test_data.VatHealModel}) - Expect(err).NotTo(HaveOccurred()) - - err = repository.Create(headerId, []interface{}{test_data.VatHealModel}) - - Expect(err).To(HaveOccurred()) - Expect(err.Error()).To(ContainSubstring("pq: duplicate key value violates unique constraint")) - }) - - It("marks the header as checked for vat heal logs", func() { - err = repository.Create(headerId, []interface{}{test_data.VatHealModel}) - Expect(err).NotTo(HaveOccurred()) - - var headerChecked bool - err = db.Get(&headerChecked, `SELECT vat_heal_checked FROM public.checked_headers WHERE header_id = $1`, headerId) - Expect(err).NotTo(HaveOccurred()) - Expect(headerChecked).To(BeTrue()) - }) - - It("updates the header to checked if checked headers row already exists", func() { - _, err = db.Exec(`INSERT INTO public.checked_headers (header_id) VALUES ($1)`, headerId) - Expect(err).NotTo(HaveOccurred()) - - err = repository.Create(headerId, []interface{}{test_data.VatHealModel}) - - Expect(err).NotTo(HaveOccurred()) - var headerChecked bool - err = db.Get(&headerChecked, `SELECT vat_heal_checked FROM public.checked_headers WHERE header_id = $1`, headerId) - Expect(err).NotTo(HaveOccurred()) - Expect(headerChecked).To(BeTrue()) - }) - - It("removes vat heal if corresponding header is deleted", func() { - err = repository.Create(headerId, []interface{}{test_data.VatHealModel}) - Expect(err).NotTo(HaveOccurred()) - - _, err = db.Exec(`DELETE FROM headers WHERE id = $1`, headerId) - - Expect(err).NotTo(HaveOccurred()) - var count int - err = db.QueryRow(`SELECT count(*) from maker.vat_heal`).Scan(&count) - Expect(err).NotTo(HaveOccurred()) - Expect(count).To(Equal(0)) - }) - - It("returns an error if the wrong model types are passed in", func() { - err = repository.Create(headerId, []interface{}{test_data.WrongModel{}}) - Expect(err).To(HaveOccurred()) - Expect(err.Error()).To(ContainSubstring("model of type test_data.WrongModel, not vat_heal.VatHealModel")) - }) - - It("wraps create in a transaction", func() { - err = repository.Create(headerId, []interface{}{test_data.VatHealModel, test_data.VatHealModel}) - Expect(err).To(HaveOccurred()) - var count int - err = db.QueryRowx(`SELECT count(*) FROM maker.vat_heal`).Scan(&count) - Expect(count).To(Equal(0)) - }) }) Describe("MissingHeaders", func() { - var ( - startingBlock, vatHealBlock, endingBlock, outsideRangeBlock int64 - blockNumbers, headerIds []int64 - ) + inputs := shared_behaviors.MissingHeadersBehaviorInputs{ + Repository: &repository, + RepositoryTwo: &vat_heal.VatHealRepository{}, + } - BeforeEach(func() { - startingBlock = rand.Int63() - vatHealBlock = startingBlock + 1 - endingBlock = startingBlock + 2 - outsideRangeBlock = startingBlock + 3 - - headerIds = []int64{} - blockNumbers = []int64{startingBlock, vatHealBlock, endingBlock, outsideRangeBlock} - for _, n := range blockNumbers { - headerId, err := headerRepository.CreateOrUpdateHeader(fakes.GetFakeHeader(n)) - Expect(err).NotTo(HaveOccurred()) - headerIds = append(headerIds, headerId) - } - }) - - It("returns headers that haven't been checked", func() { - err = repository.MarkHeaderChecked(headerIds[0]) - Expect(err).NotTo(HaveOccurred()) - - headers, err := repository.MissingHeaders(startingBlock, endingBlock) - - Expect(err).NotTo(HaveOccurred()) - Expect(headers[0].Id).To(Or(Equal(headerIds[1]), Equal(headerIds[2]))) - Expect(headers[1].Id).To(Or(Equal(headerIds[1]), Equal(headerIds[2]))) - Expect(len(headers)).To(Equal(2)) - }) - - It("returns header ids when checked_headers.vat_heal is false", func() { - err = repository.MarkHeaderChecked(headerIds[0]) - _, err = db.Exec(`INSERT INTO checked_headers (header_id) VALUES ($1)`, headerIds[1]) - Expect(err).NotTo(HaveOccurred()) - - headers, err := repository.MissingHeaders(startingBlock, endingBlock) - - Expect(err).NotTo(HaveOccurred()) - Expect(headers[0].Id).To(Or(Equal(headerIds[1]), Equal(headerIds[2]))) - Expect(headers[1].Id).To(Or(Equal(headerIds[1]), Equal(headerIds[2]))) - Expect(len(headers)).To(Equal(2)) - }) - - It("only returns header ids for the current node", func() { - db2 := test_config.NewTestDB(core.Node{ID: "second node"}) - headerRepository2 := repositories.NewHeaderRepository(db2) - repository2 := vat_heal.VatHealRepository{} - repository2.SetDB(db2) - - for _, n := range blockNumbers { - _, err = headerRepository2.CreateOrUpdateHeader(fakes.GetFakeHeader(n)) - Expect(err).NotTo(HaveOccurred()) - } - - err = repository.MarkHeaderChecked(headerIds[0]) - Expect(err).NotTo(HaveOccurred()) - - nodeOneMissingHeaders, err := repository.MissingHeaders(startingBlock, endingBlock) - Expect(err).NotTo(HaveOccurred()) - Expect(len(nodeOneMissingHeaders)).To(Equal(2)) - - nodeTwoMissingHeaders, err := repository2.MissingHeaders(startingBlock, endingBlock) - Expect(err).NotTo(HaveOccurred()) - Expect(len(nodeTwoMissingHeaders)).To(Equal(3)) - }) + shared_behaviors.SharedRepositoryMissingHeadersBehaviors(&inputs) }) Describe("MarkCheckedHeader", func() { - var headerId int64 + inputs := shared_behaviors.MarkedHeaderCheckedBehaviorInputs{ + CheckedHeaderColumnName: constants.VatHealChecked, + Repository: &repository, + } - BeforeEach(func() { - headerId, err = headerRepository.CreateOrUpdateHeader(fakes.FakeHeader) - Expect(err).NotTo(HaveOccurred()) - }) - - It("creates a new checked_header record", func() { - err := repository.MarkHeaderChecked(headerId) - Expect(err).NotTo(HaveOccurred()) - - var checkedHeaderResult = CheckedHeaderResult{} - err = db.Get(&checkedHeaderResult, `SELECT vat_heal_checked FROM checked_headers WHERE header_id = $1`, headerId) - Expect(err).NotTo(HaveOccurred()) - Expect(checkedHeaderResult.VatHealChecked).To(BeTrue()) - }) - - It("updates an existing checked header", func() { - _, err := db.Exec(`INSERT INTO checked_headers (header_id) VALUES($1)`, headerId) - Expect(err).NotTo(HaveOccurred()) - - var checkedHeaderResult CheckedHeaderResult - err = db.Get(&checkedHeaderResult, `SELECT vat_heal_checked FROM checked_headers WHERE header_id = $1`, headerId) - Expect(err).NotTo(HaveOccurred()) - Expect(checkedHeaderResult.VatHealChecked).To(BeFalse()) - - err = repository.MarkHeaderChecked(headerId) - Expect(err).NotTo(HaveOccurred()) - - err = db.Get(&checkedHeaderResult, `SELECT vat_heal_checked FROM checked_headers WHERE header_id = $1`, headerId) - Expect(err).NotTo(HaveOccurred()) - Expect(checkedHeaderResult.VatHealChecked).To(BeTrue()) - }) + shared_behaviors.SharedRepositoryMarkHeaderCheckedBehaviors(&inputs) }) })