Merge "Several cleanups suggested by mab."
diff --git a/go/client/client.go b/go/client/client.go index 4a9db0b..7938e72 100644 --- a/go/client/client.go +++ b/go/client/client.go
@@ -206,23 +206,16 @@ s.max.Sub(s.max, delta) } +// contains returns true iff p belongs to s +func (s *timeSample) contains(p *big.Int) bool { + return s.max.Cmp(p) >= 0 && s.min.Cmp(p) <= 0 +} + // overlaps returns true iff s and other have any timespan in common. func (s *timeSample) overlaps(other *timeSample) bool { return s.max.Cmp(other.min) >= 0 && other.max.Cmp(s.min) >= 0 } -// overlapsAll returns true iff s has s timespan in common with all of the -// elements of others. -func (s *timeSample) overlapsAll(others []*timeSample) bool { - for _, other := range others { - if !s.overlaps(other) { - return false - } - } - - return true -} - // query sends a request to s, appends it to chain, and returns the resulting // timeSample. func (c *Client) query(server *config.Server, chain *config.Chain) (*timeSample, error) { @@ -415,10 +408,10 @@ for _, sample := range samples[1:] { if ret.min.Cmp(sample.min) < 0 { - sample.min.Set(ret.min) + ret.min.Set(sample.min) } if ret.max.Cmp(sample.max) > 0 { - sample.max.Set(ret.max) + ret.max.Set(sample.max) } } @@ -437,11 +430,13 @@ overlapping := make([]*timeSample, 0, n) - for i, initial := range samples { - overlapping = append(overlapping, initial) + for _, initial := range samples { + // An intersection of any subset of intervals will be an interval that contains + // the starting point of one of the intervals (possibly as its own starting point). + point := initial.min - for _, candidate := range samples[i+1:] { - if candidate.overlapsAll(overlapping) { + for _, candidate := range samples { + if candidate.contains(point) { overlapping = append(overlapping, candidate) }
diff --git a/go/client/client_test.go b/go/client/client_test.go index bebec9f..d08d955 100644 --- a/go/client/client_test.go +++ b/go/client/client_test.go
@@ -17,6 +17,7 @@ import ( "crypto/rand" "encoding/json" + "math/big" "net" "strconv" "sync" @@ -333,3 +334,56 @@ addr: localAddr, }, nil } + +func TestFindNOverlapping(t *testing.T) { + type sample struct { + min int64 + max int64 + } + testcases := []struct { + samples []sample + maxN int + }{ + { + samples: []sample{ + {0, 2}, + {1, 3}, + }, + maxN: 2, + }, + { + samples: []sample{ + {0, 2}, + {1, 3}, + {4, 5}, + }, + maxN: 2, + }, + { + samples: []sample{ + {0, 10}, + {1, 2}, + {5, 10}, + {6, 10}, + }, + maxN: 3, + }, + } + for i, tc := range testcases { + samples := make([]*timeSample, len(tc.samples)) + for j, s := range tc.samples { + samples[j] = &timeSample{ + base: big.NewInt(0), + min: big.NewInt(s.min), + max: big.NewInt(s.max), + } + } + for n := 1; n <= len(samples); n++ { + expectedOk := n <= tc.maxN + _, ok := findNOverlapping(samples, n) + if ok != expectedOk { + t.Errorf("#%d: findNOverlapping(n=%d) returned %v, wanted %v", i, n, ok, expectedOk) + } + } + } +}