diff options
Diffstat (limited to 'src/mongo/gotools/common/intents/intent_prioritizer_test.go')
-rw-r--r-- | src/mongo/gotools/common/intents/intent_prioritizer_test.go | 174 |
1 files changed, 174 insertions, 0 deletions
diff --git a/src/mongo/gotools/common/intents/intent_prioritizer_test.go b/src/mongo/gotools/common/intents/intent_prioritizer_test.go new file mode 100644 index 00000000000..2abd79e5641 --- /dev/null +++ b/src/mongo/gotools/common/intents/intent_prioritizer_test.go @@ -0,0 +1,174 @@ +package intents + +import ( + "container/heap" + "github.com/mongodb/mongo-tools/common/testutil" + . "github.com/smartystreets/goconvey/convey" + "testing" +) + +func TestLegacyPrioritizer(t *testing.T) { + + testutil.VerifyTestType(t, testutil.UnitTestType) + + Convey("With a legacyPrioritizer initialized with an ordered intent list", t, func() { + testList := []*Intent{ + &Intent{DB: "1"}, + &Intent{DB: "2"}, + &Intent{DB: "3"}, + } + legacy := NewLegacyPrioritizer(testList) + So(legacy, ShouldNotBeNil) + + Convey("the priority should be defined by 'first-in-first-out'", func() { + it0 := legacy.Get() + it1 := legacy.Get() + it2 := legacy.Get() + it3 := legacy.Get() + So(it3, ShouldBeNil) + So(it0.DB, ShouldBeLessThan, it1.DB) + So(it1.DB, ShouldBeLessThan, it2.DB) + }) + }) +} + +func TestBasicDBHeapBehavior(t *testing.T) { + var dbheap heap.Interface + + testutil.VerifyTestType(t, testutil.UnitTestType) + + Convey("With an empty dbHeap", t, func() { + dbheap = &DBHeap{} + heap.Init(dbheap) + + Convey("when inserting unordered dbCounters with different active counts", func() { + heap.Push(dbheap, &dbCounter{75, nil}) + heap.Push(dbheap, &dbCounter{121, nil}) + heap.Push(dbheap, &dbCounter{76, nil}) + heap.Push(dbheap, &dbCounter{51, nil}) + heap.Push(dbheap, &dbCounter{82, nil}) + heap.Push(dbheap, &dbCounter{117, nil}) + heap.Push(dbheap, &dbCounter{49, nil}) + heap.Push(dbheap, &dbCounter{101, nil}) + heap.Push(dbheap, &dbCounter{122, nil}) + heap.Push(dbheap, &dbCounter{33, nil}) + heap.Push(dbheap, &dbCounter{0, nil}) + + Convey("they should pop in active order, least to greatest", func() { + prev := -1 + for dbheap.Len() > 0 { + popped := heap.Pop(dbheap).(*dbCounter) + So(popped.active, ShouldBeGreaterThan, prev) + prev = popped.active + } + }) + }) + + Convey("when inserting unordered dbCounters with different bson sizes", func() { + heap.Push(dbheap, &dbCounter{0, []*Intent{&Intent{Size: 70}}}) + heap.Push(dbheap, &dbCounter{0, []*Intent{&Intent{Size: 1024}}}) + heap.Push(dbheap, &dbCounter{0, []*Intent{&Intent{Size: 97}}}) + heap.Push(dbheap, &dbCounter{0, []*Intent{&Intent{Size: 3}}}) + heap.Push(dbheap, &dbCounter{0, []*Intent{&Intent{Size: 1024 * 1024}}}) + + Convey("they should pop in bson size order, greatest to least", func() { + prev := int64(1024*1024 + 1) // Maximum + for dbheap.Len() > 0 { + popped := heap.Pop(dbheap).(*dbCounter) + So(popped.collections[0].Size, ShouldBeLessThan, prev) + prev = popped.collections[0].Size + } + }) + }) + }) +} + +func TestDBCounterCollectionSorting(t *testing.T) { + + testutil.VerifyTestType(t, testutil.UnitTestType) + + Convey("With a dbCounter and an unordered collection of intents", t, func() { + dbc := &dbCounter{ + collections: []*Intent{ + &Intent{Size: 100}, + &Intent{Size: 1000}, + &Intent{Size: 1}, + &Intent{Size: 10}, + }, + } + + Convey("popping the sorted intents should return in decreasing BSONSize", func() { + dbc.SortCollectionsBySize() + So(dbc.PopIntent().Size, ShouldEqual, 1000) + So(dbc.PopIntent().Size, ShouldEqual, 100) + So(dbc.PopIntent().Size, ShouldEqual, 10) + So(dbc.PopIntent().Size, ShouldEqual, 1) + So(dbc.PopIntent(), ShouldBeNil) + So(dbc.PopIntent(), ShouldBeNil) + }) + }) +} + +func TestSimulatedMultiDBJob(t *testing.T) { + var prioritizer IntentPrioritizer + + testutil.VerifyTestType(t, testutil.UnitTestType) + + Convey("With a prioritizer initialized with a set of intents", t, func() { + intents := []*Intent{ + &Intent{C: "small", DB: "db2", Size: 32}, + &Intent{C: "medium", DB: "db2", Size: 128}, + &Intent{C: "giant", DB: "db1", Size: 1024}, + &Intent{C: "tiny", DB: "db1", Size: 2}, + } + prioritizer = NewMultiDatabaseLTFPrioritizer(intents) + So(prioritizer, ShouldNotBeNil) + + Convey("and a running simulation of two jobs threads:", func() { + Convey("the first two intents should be of different dbs", func() { + i0 := prioritizer.Get() + So(i0, ShouldNotBeNil) + i1 := prioritizer.Get() + So(i1, ShouldNotBeNil) + + Convey("the first intent should be the largest bson file", func() { + So(i0.C, ShouldEqual, "giant") + So(i0.DB, ShouldEqual, "db1") + }) + + Convey("the second intent should be the largest bson file of db2", func() { + So(i1.C, ShouldEqual, "medium") + So(i1.DB, ShouldEqual, "db2") + }) + + Convey("with the second job finishing the smaller intents", func() { + prioritizer.Finish(i1) + i2 := prioritizer.Get() + So(i2, ShouldNotBeNil) + prioritizer.Finish(i2) + i3 := prioritizer.Get() + So(i3, ShouldNotBeNil) + + Convey("the next job should be from db2", func() { + So(i2.C, ShouldEqual, "small") + So(i2.DB, ShouldEqual, "db2") + }) + + Convey("the final job should be from db1", func() { + So(i3.C, ShouldEqual, "tiny") + So(i3.DB, ShouldEqual, "db1") + + Convey("which means that there should be two active db1 jobs", func() { + counter := prioritizer.(*multiDatabaseLTFPrioritizer).counterMap["db1"] + So(counter.active, ShouldEqual, 2) + }) + }) + + Convey("the heap should now be empty", func() { + So(prioritizer.(*multiDatabaseLTFPrioritizer).dbHeap.Len(), ShouldEqual, 0) + }) + }) + }) + }) + }) +} |