Last active
October 17, 2015 18:54
-
-
Save danieleli/7de3762e880dab4031d2 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package paging | |
import "fmt" | |
// SearchWindow contains start and stop | |
// and a default method for spliting the | |
// window into smaller windows | |
type SearchWindow struct { | |
start int64 | |
stop int64 | |
} | |
func (w *SearchWindow) SplitWindow() (SearchWindow, SearchWindow) { | |
midPoint := w.start + ((w.stop - w.start) / 2) | |
w1 := SearchWindow{ | |
start: w.start, | |
stop: midPoint, | |
} | |
w2 := SearchWindow{ | |
start: midPoint + 1, | |
stop: w.stop, | |
} | |
return w1, w2 | |
} | |
// IntSearch is the interface for the remote api | |
type IntSearcher interface { | |
Search(inputs SearchWindow) []int | |
} | |
// PagedSearchCommand encapsulates paging logic | |
type PagedSearchCommand struct { | |
remoteApi IntSearcher | |
maxPageSize int | |
debug bool | |
} | |
func (cmd *PagedSearchCommand) Execute(w SearchWindow) []int { | |
if cmd.debug { | |
fmt.Println("Window: ", w) | |
} | |
items := cmd.remoteApi.Search(w) | |
if len(items) <= cmd.maxPageSize { | |
return items | |
} | |
w1, w2 := w.SplitWindow() | |
firstHalf := cmd.Execute(w1) | |
secondHalf := cmd.Execute(w2) | |
return append(firstHalf, secondHalf...) | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package paging | |
import ( | |
"testing" | |
"fmt" | |
) | |
func TestMe(t *testing.T) { | |
for _, datum := range testData { | |
datum.RunTest(t) | |
} | |
} | |
var testData = []testDatum{ | |
{"Stop(10000) exceeeds total available(99)", 5, 70, 10000, 30}, | |
{"PageSize(5) < total available(99)", 5, 1, 30, 30}, | |
{"MaxPageSize > total available(99)", 99000, 1, 9000, 99}, | |
{"MaxPageSize = total returned(99)", 10, 1, 10, 10}, | |
{"MaxPageSize == returnCount - 1", 9, 1, 10, 10}, | |
{"MaxPageSize == returnCount + 1", 11, 1, 10, 10}, | |
{"MaxPageSize == 1", 1, 1, 10, 10}, | |
} | |
type testDatum struct { | |
name string | |
max int | |
start int | |
stop int | |
expectedCount int | |
} | |
func (me *testDatum) RunTest(t *testing.T) { | |
fmt.Println("Test Name: ", me.name) | |
api := NewMockApi(me.max) | |
pagedSearch := PagedSearchCommand{ | |
remoteApi: api, | |
maxPageSize: me.max, | |
} | |
w := SearchWindow{ | |
start: int64(me.start), | |
stop: int64(me.stop), | |
} | |
items := pagedSearch.Execute (w) | |
actualCount := len(items) | |
if actualCount != me.expectedCount { | |
fmt.Println(items) | |
fmt.Printf("\nexpected %v \nactual %v\n", me.expectedCount, actualCount) | |
t.FailNow() | |
} | |
} | |
// --------- | |
// MockApi | |
// --------- | |
func NewMockApi(maxPageSize int) *MockApi { | |
values := []int{} | |
for i := 0; i < 100; i++ { | |
values = append(values, i) | |
} | |
api := MockApi{ | |
values: values, | |
maxPageSize: int64(maxPageSize), | |
} | |
return &api | |
} | |
type MockApi struct { | |
values []int | |
maxPageSize int64 | |
} | |
func (api *MockApi) Search(w SearchWindow) []int { | |
allItemCount := int64(len(api.values)) | |
rtn := []int{} | |
for i := w.start; i <= w.stop; i++ { | |
hasMoreValues := i < allItemCount | |
isMaxSize := (i - w.start) > api.maxPageSize | |
if !hasMoreValues || isMaxSize { | |
return rtn | |
} | |
rtn = append(rtn, api.values[i]) | |
} | |
return rtn | |
} | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment