diff options
author | Alexander Mazuruk <a.mazuruk@samsung.com> | 2018-08-15 14:41:49 +0200 |
---|---|---|
committer | Pawel Wieczorek <p.wieczorek2@samsung.com> | 2018-10-01 16:34:14 +0200 |
commit | 4c2c6886cebdf8acbca4e1165e7ec8bc793eeb5d (patch) | |
tree | db52fc7a91e1f3819fd63a4282cca9994162d901 | |
parent | a4ae7889d804f7d784a1cc9d65d2a68cef446a6e (diff) | |
download | weles-4c2c6886cebdf8acbca4e1165e7ec8bc793eeb5d.tar.gz weles-4c2c6886cebdf8acbca4e1165e7ec8bc793eeb5d.tar.bz2 weles-4c2c6886cebdf8acbca4e1165e7ec8bc793eeb5d.zip |
Adjust database tests
Make artifacts/database tests faster (8s->2.5s) by restructurizing
before/afterEach clauses to omit unneccessary setup before TCs.
Finished packing setups into single transactions with db.
Merged tests for pagination into database tests.
Add tests for sorting
Less magic
Change-Id: I49c82c4d0bfc000498b555c0d56490d939e24713
Signed-off-by: Alexander Mazuruk <a.mazuruk@samsung.com>
-rw-r--r-- | artifacts/database/database_suite_test.go | 32 | ||||
-rw-r--r-- | artifacts/database/database_test.go | 408 | ||||
-rw-r--r-- | artifacts/database/pagination_test.go | 96 |
3 files changed, 288 insertions, 248 deletions
diff --git a/artifacts/database/database_suite_test.go b/artifacts/database/database_suite_test.go index 1bd072f..27a1ee0 100644 --- a/artifacts/database/database_suite_test.go +++ b/artifacts/database/database_suite_test.go @@ -38,26 +38,42 @@ var ( tmpDirPath string ) +const ( + dbToRead = "test-db-pagination.db" + tmpDirPrefix = "weles-" + generatedRecordsCount = 100 + pageLimit = 30 + pageCount = generatedRecordsCount/pageLimit + 1 +) + var _ = BeforeSuite(func() { + var ( + err error + db ArtifactDB + ) - var err error - tmpDirPath, err = ioutil.TempDir("", "weles-") + tmpDirPath, err = ioutil.TempDir("", tmpDirPrefix) Expect(err).ToNot(HaveOccurred()) - err = silverHoneybadger.Open(filepath.Join(tmpDirPath, "test_pagination.db")) + + err = db.Open(filepath.Join(tmpDirPath, dbToRead)) Expect(err).ToNot(HaveOccurred()) - artifacts := fixtures.CreateArtifactInfoSlice(100) - trans, err := silverHoneybadger.dbmap.Begin() + silverHoneybadgerArtifacts := fixtures.CreateArtifactInfoSlice(generatedRecordsCount) + + trans, err := db.dbmap.Begin() Expect(err).ToNot(HaveOccurred()) - for _, artifact := range artifacts { - err = silverHoneybadger.InsertArtifactInfo(&artifact) + + for _, artifact := range silverHoneybadgerArtifacts { + err = trans.Insert(&artifact) Expect(err).ToNot(HaveOccurred()) } trans.Commit() + db.Close() + err = silverHoneybadger.Open(filepath.Join(tmpDirPath, dbToRead)) + Expect(err).ToNot(HaveOccurred()) }) var _ = AfterSuite(func() { - err := silverHoneybadger.Close() Expect(err).ToNot(HaveOccurred()) err = os.RemoveAll(tmpDirPath) diff --git a/artifacts/database/database_test.go b/artifacts/database/database_test.go index bb9debc..1b96839 100644 --- a/artifacts/database/database_test.go +++ b/artifacts/database/database_test.go @@ -40,8 +40,6 @@ var _ = Describe("ArtifactDB", func() { invalidStatus weles.ArtifactStatus = "invalidStatus" invalidType weles.ArtifactType = "invalidType" invalidAlias weles.ArtifactAlias = "invalidAlias" - goldenUnicorn ArtifactDB - tmpDir string artifact = weles.ArtifactInfo{ ArtifactDescription: weles.ArtifactDescription{ @@ -174,180 +172,302 @@ var _ = Describe("ArtifactDB", func() { Alias: nil, } emptyFilter = weles.ArtifactFilter{} - //default values of sorter passed by server - defaultSorter = weles.ArtifactSorter{ + + emptyPaginator = weles.ArtifactPagination{} + + descendingSorter = weles.ArtifactSorter{ SortOrder: weles.SortOrderDescending, SortBy: weles.ArtifactSortByID, } - ) - - jobsInDB := func(job weles.JobID) int64 { - n, err := goldenUnicorn.dbmap.SelectInt(`SELECT COUNT(*) - FROM artifacts - WHERE JobID = ?`, job) - Expect(err).ToNot(HaveOccurred()) - return n - } - BeforeEach(func() { - var err error - tmpDir, err = ioutil.TempDir("", "weles-") - Expect(err).ToNot(HaveOccurred()) - err = goldenUnicorn.Open(filepath.Join(tmpDir, "test.db")) - Expect(err).ToNot(HaveOccurred()) - }) - - AfterEach(func() { - err := goldenUnicorn.Close() - Expect(err).ToNot(HaveOccurred()) - err = os.RemoveAll(tmpDir) - Expect(err).ToNot(HaveOccurred()) - }) + defaultSorter = descendingSorter - It("should open new database, with artifact table", func() { - n, err := goldenUnicorn.dbmap.SelectInt(`SELECT COUNT(*) - FROM sqlite_master - WHERE name = 'artifacts' - AND type = 'table'`) + ascendingSorter = weles.ArtifactSorter{ + SortOrder: weles.SortOrderAscending, + SortBy: weles.ArtifactSortByID, + } + ) + jobInDB := func(job weles.JobID, db ArtifactDB) bool { + n, err := db.dbmap.SelectInt( + `SELECT COUNT(*) + FROM artifacts + WHERE JobID = ?`, job) Expect(err).ToNot(HaveOccurred()) - Expect(n).To(BeNumerically("==", 1)) - }) + return bool(n > 0) + } - It("should fail to open database on invalid path", func() { - // sql.Open only validates arguments. - // db.Ping must be called to check the connection. - invalidDatabasePath := filepath.Join(tmpDir, "invalid", "test.db") - err := goldenUnicorn.Open(invalidDatabasePath) - Expect(err).To(HaveOccurred()) - Expect(invalidDatabasePath).ToNot(BeAnExistingFile()) - }) + Describe("Not pagination", func() { - It("should insert new artifact to database", func() { - Expect(jobsInDB(job)).To(BeNumerically("==", 0)) + var ( + goldenUnicorn ArtifactDB + tmpDir string + ) + BeforeEach(func() { + var err error + tmpDir, err = ioutil.TempDir("", tmpDirPrefix) + Expect(err).ToNot(HaveOccurred()) + err = goldenUnicorn.Open(filepath.Join(tmpDir, "test.db")) + Expect(err).ToNot(HaveOccurred()) + }) - err := goldenUnicorn.InsertArtifactInfo(&artifact) - Expect(err).ToNot(HaveOccurred()) + AfterEach(func() { + err := goldenUnicorn.Close() + Expect(err).ToNot(HaveOccurred()) + err = os.RemoveAll(tmpDir) + Expect(err).ToNot(HaveOccurred()) + }) + It("should open new database, with artifact table", func() { + n, err := goldenUnicorn.dbmap.SelectInt( + `SELECT COUNT(*) + FROM sqlite_master + WHERE name = 'artifacts' + AND type = 'table'`) + Expect(err).ToNot(HaveOccurred()) + Expect(n).To(BeNumerically("==", 1)) + }) - Expect(jobsInDB(artifact.JobID)).To(BeNumerically("==", 1)) - }) + It("should fail to open database on invalid path", func() { + // sql.Open only validates arguments. + // db.Ping must be called to check the connection. + invalidDatabasePath := filepath.Join(tmpDir, "invalid", "test.db") + err := goldenUnicorn.Open(invalidDatabasePath) + Expect(err).To(HaveOccurred()) + Expect(invalidDatabasePath).ToNot(BeAnExistingFile()) + }) - Describe("SelectPath", func() { + It("should insert new artifact to database", func() { + Expect(jobInDB(job, goldenUnicorn)).To(BeFalse()) - BeforeEach(func() { err := goldenUnicorn.InsertArtifactInfo(&artifact) Expect(err).ToNot(HaveOccurred()) - Expect(jobsInDB(artifact.JobID)).To(BeNumerically("==", 1)) + Expect(jobInDB(artifact.JobID, goldenUnicorn)).To(BeTrue()) }) - DescribeTable("database selectpath", - func(path weles.ArtifactPath, expectedErr error, expectedArtifact weles.ArtifactInfo) { - result, err := goldenUnicorn.SelectPath(path) - - if expectedErr != nil { - Expect(err).To(Equal(expectedErr)) - } else { + Describe("SetStatus", func() { + BeforeEach(func() { + trans, err := goldenUnicorn.dbmap.Begin() + Expect(err).ToNot(HaveOccurred()) + defer trans.Commit() + for _, a := range testArtifacts { + err := trans.Insert(&a) Expect(err).ToNot(HaveOccurred()) } - expectedArtifact.ID = result.ID - Expect(result).To(Equal(expectedArtifact)) - }, - Entry("retrieve artifact based on path", - artifact.Path, nil, artifact), - Entry("retrieve artifact based on invalid path", - invalidPath, sql.ErrNoRows, weles.ArtifactInfo{}), - ) - }) + }) + DescribeTable("artifact status change", + func(change weles.ArtifactStatusChange, expectedErr error) { + var a weles.ArtifactInfo + err := goldenUnicorn.SetStatus(change) + if expectedErr == nil { + Expect(err).ToNot(HaveOccurred()) + a, err = goldenUnicorn.SelectPath(change.Path) + Expect(err).ToNot(HaveOccurred()) + Expect(a.Status).To(Equal(change.NewStatus)) + } else { + Expect(err).To(Equal(expectedErr)) + a, err = goldenUnicorn.SelectPath(change.Path) + Expect(err).To(HaveOccurred()) + Expect(a).To(Equal(weles.ArtifactInfo{})) + } + }, + Entry("change status of artifact not present in ArtifactDB", + weles.ArtifactStatusChange{ + Path: invalidPath, + NewStatus: weles.ArtifactStatusDOWNLOADING, + }, + sql.ErrNoRows), + Entry("change status of artifact present in ArtifactDB", + weles.ArtifactStatusChange{ + Path: artifact.Path, + NewStatus: weles.ArtifactStatusDOWNLOADING, + }, + nil), + ) + }) - Describe("List", func() { - BeforeEach(func() { - trans, err := goldenUnicorn.dbmap.Begin() - Expect(err).ToNot(HaveOccurred()) - defer trans.Commit() - for _, a := range testArtifacts { - err := trans.Insert(&a) + Describe("SelectPath", func() { + + BeforeEach(func() { + err := goldenUnicorn.InsertArtifactInfo(&artifact) Expect(err).ToNot(HaveOccurred()) - } + + Expect(jobInDB(artifact.JobID, goldenUnicorn)).To(BeTrue()) + }) + + DescribeTable("database selectpath", + func(path weles.ArtifactPath, expectedErr error, + expectedArtifact weles.ArtifactInfo) { + result, err := goldenUnicorn.SelectPath(path) + + if expectedErr != nil { + Expect(err).To(Equal(expectedErr)) + } else { + Expect(err).ToNot(HaveOccurred()) + } + expectedArtifact.ID = result.ID + Expect(result).To(Equal(expectedArtifact)) + }, + Entry("retrieve artifact based on path", artifact.Path, nil, artifact), + Entry("retrieve artifact based on invalid path", invalidPath, sql.ErrNoRows, + weles.ArtifactInfo{}), + ) }) - DescribeTable("list artifacts matching filter", - func(filter weles.ArtifactFilter, expected ...weles.ArtifactInfo) { - results, _, err := goldenUnicorn.Filter(filter, defaultSorter, - weles.ArtifactPagination{}) + + Describe("List", func() { + BeforeEach(func() { + trans, err := goldenUnicorn.dbmap.Begin() Expect(err).ToNot(HaveOccurred()) - //TODO: match all fields except ID. - for i := range results { - for j := range expected { - if results[i].JobID == expected[j].JobID { - if results[i].URI == expected[j].URI { - expected[j].ID = results[i].ID + defer trans.Commit() + for _, a := range testArtifacts { + err := trans.Insert(&a) + Expect(err).ToNot(HaveOccurred()) + } + }) + DescribeTable("list artifacts matching filter", + func(filter weles.ArtifactFilter, expected ...weles.ArtifactInfo) { + results, _, err := goldenUnicorn.Filter(filter, defaultSorter, emptyPaginator) + Expect(err).ToNot(HaveOccurred()) + //TODO: match all fields except ID. + for i := range results { + for j := range expected { + if results[i].JobID == expected[j].JobID { + if results[i].URI == expected[j].URI { + expected[j].ID = results[i].ID + } } } } + Expect(results).To(ConsistOf(expected)) + }, + Entry("filter one JobID", oneJobFilter, artifact), + Entry("filter more than one JobIDs", twoJobsFilter, artifact, aImageReady, + aYamlFailed), + Entry("filter one Type", oneTypeFilter, aYamlFailed), + Entry("filter more than one Type", twoTypesFilter, aYamlFailed, aTestFailed), + Entry("filter one Status", oneStatusFilter, artifact), + Entry("filter more than one Status", twoStatusFilter, artifact, aTestFailed, + aYamlFailed), + Entry("filter one Alias", oneAliasFilter, artifact), + Entry("filter more than one Alias", twoAliasFilter, artifact, aImageReady, + aYamlFailed), + Entry("filter is completly set up", fullFilter, aYamlFailed), + Entry("filter is empty", emptyFilter, artifact, aImageReady, aYamlFailed, + aTestFailed), + ) + DescribeTable("return artifact not found error", + func(filter weles.ArtifactFilter, expected ...weles.ArtifactInfo) { + _, _, err := goldenUnicorn.Filter(filter, defaultSorter, emptyPaginator) + Expect(err).To(Equal(weles.ErrArtifactNotFound)) + }, + Entry("filter JobID not in db", noJobFilter), + Entry("filter Type not in db", noTypeFilter), + Entry("filter Status not in db", noStatusFilter), + Entry("filter Alias not in db", noAliasFilter), + Entry("no artifact in db matches filter", noMatchFilter), + ) + }) + Describe("Sorting", func() { + BeforeEach(func() { + trans, err := goldenUnicorn.dbmap.Begin() + Expect(err).ToNot(HaveOccurred()) + defer trans.Commit() + for _, a := range testArtifacts { + err := trans.Insert(&a) + Expect(err).ToNot(HaveOccurred()) } - Expect(results).To(ConsistOf(expected)) - }, - Entry("filter one JobID", oneJobFilter, artifact), - Entry("filter more than one JobIDs", twoJobsFilter, artifact, aImageReady, aYamlFailed), - Entry("filter one Type", oneTypeFilter, aYamlFailed), - Entry("filter more than one Type", twoTypesFilter, aYamlFailed, aTestFailed), - Entry("filter one Status", oneStatusFilter, artifact), - Entry("filter more than one Status", twoStatusFilter, artifact, aTestFailed, - aYamlFailed), - Entry("filter one Alias", oneAliasFilter, artifact), - Entry("filter more than one Alias", twoAliasFilter, artifact, aImageReady, aYamlFailed), - Entry("filter is completly set up", fullFilter, aYamlFailed), - Entry("filter is empty", emptyFilter, artifact, aImageReady, aYamlFailed, aTestFailed), - ) + }) + DescribeTable("Should return correctly sorted artifacts", + func(sorter weles.ArtifactSorter) { + result, _, err := goldenUnicorn.Filter(emptyFilter, sorter, emptyPaginator) + Expect(err).ToNot(HaveOccurred()) + var currID int + if sorter.SortOrder == weles.SortOrderAscending { + for _, a := range result { + if currID == 0 { + currID = int(a.ID) + continue + } + Expect(a.ID).To(BeEquivalentTo(currID + 1)) + currID = int(a.ID) + } + } else { + for _, a := range result { + if currID == 0 { + currID = int(a.ID) + continue + } + Expect(a.ID).To(BeEquivalentTo(currID - 1)) + currID = int(a.ID) + } + } + }, + Entry("By ID, Ascending", ascendingSorter), + Entry("By ID, Descending", descendingSorter), + ) - DescribeTable("return artifact not found error", - func(filter weles.ArtifactFilter, expected ...weles.ArtifactInfo) { - _, _, err := goldenUnicorn.Filter(filter, defaultSorter, weles.ArtifactPagination{}) - Expect(err).To(Equal(weles.ErrArtifactNotFound)) - }, - Entry("filter JobID not in db", noJobFilter), - Entry("filter Type not in db", noTypeFilter), - Entry("filter Status not in db", noStatusFilter), - Entry("filter Alias not in db", noAliasFilter), - Entry("no artifact in db matches filter", noMatchFilter), - ) - }) - Describe("SetStatus", func() { - BeforeEach(func() { - for _, a := range testArtifacts { - err := goldenUnicorn.InsertArtifactInfo(&a) - Expect(err).ToNot(HaveOccurred()) - } }) - DescribeTable("artifact status change", - func(change weles.ArtifactStatusChange, expectedErr error) { + }) + Describe("Pagination", func() { + Context("Database is filled with generatedRecordsCount records", func() { + DescribeTable("paginating through artifacts", + func(paginator weles.ArtifactPagination, + expectedResponseLength, expectedRemainingRecords int) { - var a weles.ArtifactInfo - err := goldenUnicorn.SetStatus(change) - if expectedErr == nil { + result, list, err := silverHoneybadger.Filter(emptyFilter, defaultSorter, paginator) Expect(err).ToNot(HaveOccurred()) - a, err = goldenUnicorn.SelectPath(change.Path) - Expect(err).ToNot(HaveOccurred()) - Expect(a.Status).To(Equal(change.NewStatus)) - } else { - Expect(err).To(Equal(expectedErr)) - a, err = goldenUnicorn.SelectPath(change.Path) - Expect(err).To(HaveOccurred()) - Expect(a).To(Equal(weles.ArtifactInfo{})) - } - }, - Entry("change status of artifact not present in ArtifactDB", - weles.ArtifactStatusChange{ - Path: invalidPath, - NewStatus: weles.ArtifactStatusDOWNLOADING, - }, - sql.ErrNoRows), - Entry("change status of artifact present in ArtifactDB", - weles.ArtifactStatusChange{ - Path: artifact.Path, - NewStatus: weles.ArtifactStatusDOWNLOADING, + + Expect(len(result)).To(BeEquivalentTo(expectedResponseLength)) + Expect(list.TotalRecords).To(BeEquivalentTo(generatedRecordsCount)) + Expect(list.RemainingRecords).To(BeEquivalentTo(expectedRemainingRecords)) }, - nil), - ) + // please keep in mind that data is sorted in descending order. + Entry("first and last page (limit is 0)", + weles.ArtifactPagination{ID: 0, Limit: 0, Forward: true}, + generatedRecordsCount, 0), + + Entry("first page, paginating forward", + weles.ArtifactPagination{ID: 0, Limit: pageLimit, Forward: true}, + pageLimit, (generatedRecordsCount-pageLimit)), + + Entry("second page, paginating forward", + weles.ArtifactPagination{ + ID: (generatedRecordsCount - pageLimit + 1), + Limit: pageLimit, + Forward: true, + }, + pageLimit, + (generatedRecordsCount-(2*pageLimit))), + + Entry("last page, paginating forward", + weles.ArtifactPagination{ + ID: int64(generatedRecordsCount - + (pageLimit * int(generatedRecordsCount/pageLimit)) + 1), + Limit: pageLimit, + Forward: true, + }, + generatedRecordsCount-(pageLimit*(pageCount-1)), + 0), + + Entry("second to last page, paginating backward", + weles.ArtifactPagination{ + ID: int64(generatedRecordsCount - + (pageLimit * int(generatedRecordsCount/pageLimit))), + Limit: pageLimit, + Forward: false, + }, + pageLimit, + pageLimit*(pageCount-2)), + + Entry("first page, paginating backward", + weles.ArtifactPagination{ + ID: int64(generatedRecordsCount - pageLimit), + Limit: pageLimit, + Forward: false, + }, + pageLimit, + 0), + ) + }) }) }) diff --git a/artifacts/database/pagination_test.go b/artifacts/database/pagination_test.go deleted file mode 100644 index 7d128aa..0000000 --- a/artifacts/database/pagination_test.go +++ /dev/null @@ -1,96 +0,0 @@ -/* - * Copyright (c) 2017-2018 Samsung Electronics Co., Ltd All Rights Reserved - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License - */ - -package database - -import ( - . "github.com/onsi/ginkgo" - . "github.com/onsi/ginkgo/extensions/table" - . "github.com/onsi/gomega" - - "git.tizen.org/tools/weles" -) - -//TODO: add some consts and limit 'magic' to multipliers - -var _ = Describe("ArtifactDB pagination", func() { - - emptyF := weles.ArtifactFilter{} - //below struct is not empty but filled with default values passed from server. - descS := weles.ArtifactSorter{ - SortOrder: weles.SortOrderDescending, - SortBy: weles.ArtifactSortByID, - } - ascS := weles.ArtifactSorter{ - SortOrder: weles.SortOrderAscending, - SortBy: weles.ArtifactSortByID, - } - Context("Database is filled with 100 records", func() { - DescribeTable("paginating through artifacts", - func( - filter weles.ArtifactFilter, - paginator weles.ArtifactPagination, - sorter weles.ArtifactSorter, - expectedResponseLength, expectedTotalRecords, expectedRemainingRecords int) { - result, list, err := silverHoneybadger.Filter(filter, sorter, paginator) - Expect(err).ToNot(HaveOccurred()) - Expect(len(result)).To(BeEquivalentTo(expectedResponseLength)) - Expect(list.TotalRecords).To(BeEquivalentTo(expectedTotalRecords)) - Expect(list.RemainingRecords).To(BeEquivalentTo(expectedRemainingRecords)) - }, - Entry("p1/1, no limit, forward, sort desc", emptyF, - weles.ArtifactPagination{Forward: true}, - descS, 100, 100, 0), - Entry("p1/4, limit 30, forward, sort desc", emptyF, - weles.ArtifactPagination{Limit: 30, Forward: true}, - descS, 30, 100, 70), - Entry("p2/4, limit 30, forward, sort desc", emptyF, - weles.ArtifactPagination{ID: 71, Limit: 30, Forward: true}, - descS, 30, 100, 40), - Entry("p3/4, limit 30, forward, sort desc", emptyF, - weles.ArtifactPagination{ID: 41, Limit: 30, Forward: true}, - descS, 30, 100, 10), - Entry("p4/4, limit 30, forward, sort desc", emptyF, - weles.ArtifactPagination{ID: 11, Limit: 30, Forward: true}, - descS, 10, 100, 0), - Entry("p3/4, limit 30, backward, sort desc", emptyF, - weles.ArtifactPagination{ID: 10, Limit: 30, Forward: false}, - descS, 30, 100, 60), - Entry("p2/4, limit 30, backward, sort desc", emptyF, - weles.ArtifactPagination{ID: 40, Limit: 30, Forward: false}, - descS, 30, 100, 30), - Entry("p1/4, limit 30, backward, sort desc", emptyF, - weles.ArtifactPagination{ID: 70, Limit: 30, Forward: false}, - descS, 30, 100, 0), - Entry("p1/1, no limit, forward, sort asc", emptyF, - weles.ArtifactPagination{Forward: true}, - ascS, 100, 100, 0), - Entry("1/4, no limit, forward, sort asc", emptyF, - weles.ArtifactPagination{Limit: 30, Forward: true}, - ascS, 30, 100, 70), - Entry("p2/4, no limit, forward, sort asc", emptyF, - weles.ArtifactPagination{ID: 30, Limit: 30, Forward: true}, - ascS, 30, 100, 40), - Entry("p3/4, no limit, forward, sort asc", emptyF, - weles.ArtifactPagination{ID: 60, Limit: 30, Forward: true}, - ascS, 30, 100, 10), - Entry("p4/4, no limit, forward, sort asc", emptyF, - weles.ArtifactPagination{ID: 90, Limit: 30, Forward: true}, - ascS, 10, 100, 0), - ) - }) - -}) |