-
Notifications
You must be signed in to change notification settings - Fork 2.5k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add Storage Integration Testing (#236)
* create integration test framework for storage + create elasticsearch integration test * refactor queries format * rename comparison fns to fit its behavior * fix rand.Uint64() (does not exist in go1.7) * revert env var check * refactor trace w/ query checker to separate file + test * import list reorder * change itest direction * change integration test format * make fmt/lint * make fmt/lint * prettify output when test fails * fmt * delete query to trace checker * remove unnecessary code * add integration test script * fix syntax * add comment about fixtures and queries * fix travis yml to run es integ test * remove es integ test from install travis * fix typo * fix err check bug * fmt * move sorting fns to model * fix imports * fix code reviews * change trace fixtures to describe the trace * revert idl * trust people * sort refactored * fix trace comparison test + raise timeout for es-integration test * code review * remove numtraces check * add multiple-trace test case * code review
- Loading branch information
Showing
36 changed files
with
2,282 additions
and
9 deletions.
There are no files selected for viewing
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
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
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,97 @@ | ||
// Copyright (c) 2017 Uber Technologies, Inc. | ||
// | ||
// Permission is hereby granted, free of charge, to any person obtaining a copy | ||
// of this software and associated documentation files (the "Software"), to deal | ||
// in the Software without restriction, including without limitation the rights | ||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | ||
// copies of the Software, and to permit persons to whom the Software is | ||
// furnished to do so, subject to the following conditions: | ||
// | ||
// The above copyright notice and this permission notice shall be included in | ||
// all copies or substantial portions of the Software. | ||
// | ||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN | ||
// THE SOFTWARE. | ||
|
||
package model | ||
|
||
import ( | ||
"sort" | ||
) | ||
|
||
type traceByTraceID []*Trace | ||
|
||
func (s traceByTraceID) Len() int { return len(s) } | ||
func (s traceByTraceID) Swap(i, j int) { s[i], s[j] = s[j], s[i] } | ||
func (s traceByTraceID) Less(i, j int) bool { | ||
if len(s[i].Spans) == 0 { | ||
return true | ||
} else if len(s[j].Spans) == 0 { | ||
return false | ||
} else { | ||
return s[i].Spans[0].TraceID.Low < s[j].Spans[0].TraceID.Low | ||
} | ||
} | ||
|
||
// SortTraces deep sorts a list of traces by TraceID. | ||
func SortTraces(traces []*Trace) { | ||
sort.Sort(traceByTraceID(traces)) | ||
for _, trace := range traces { | ||
SortTrace(trace) | ||
} | ||
} | ||
|
||
type spanBySpanID []*Span | ||
|
||
func (s spanBySpanID) Len() int { return len(s) } | ||
func (s spanBySpanID) Swap(i, j int) { s[i], s[j] = s[j], s[i] } | ||
func (s spanBySpanID) Less(i, j int) bool { return s[i].SpanID < s[j].SpanID } | ||
|
||
// SortTrace deep sorts a trace's spans by SpanID. | ||
func SortTrace(trace *Trace) { | ||
sort.Sort(spanBySpanID(trace.Spans)) | ||
for _, span := range trace.Spans { | ||
sortSpan(span) | ||
} | ||
} | ||
|
||
func sortSpan(span *Span) { | ||
span.NormalizeTimestamps() | ||
sortTags(span.Tags) | ||
sortLogs(span.Logs) | ||
sortProcess(span.Process) | ||
} | ||
|
||
type tagByKey []KeyValue | ||
|
||
func (t tagByKey) Len() int { return len(t) } | ||
func (t tagByKey) Swap(i, j int) { t[i], t[j] = t[j], t[i] } | ||
func (t tagByKey) Less(i, j int) bool { return t[i].Key < t[j].Key } | ||
|
||
func sortTags(tags []KeyValue) { | ||
sort.Sort(tagByKey(tags)) | ||
} | ||
|
||
type logByTimestamp []Log | ||
|
||
func (t logByTimestamp) Len() int { return len(t) } | ||
func (t logByTimestamp) Swap(i, j int) { t[i], t[j] = t[j], t[i] } | ||
func (t logByTimestamp) Less(i, j int) bool { return t[i].Timestamp.Before(t[j].Timestamp) } | ||
|
||
func sortLogs(logs []Log) { | ||
sort.Sort(logByTimestamp(logs)) | ||
for _, log := range logs { | ||
sortTags(log.Fields) | ||
} | ||
} | ||
|
||
func sortProcess(process *Process) { | ||
if process != nil { | ||
sortTags(process.Tags) | ||
} | ||
} |
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,126 @@ | ||
// Copyright (c) 2017 Uber Technologies, Inc. | ||
// | ||
// Permission is hereby granted, free of charge, to any person obtaining a copy | ||
// of this software and associated documentation files (the "Software"), to deal | ||
// in the Software without restriction, including without limitation the rights | ||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | ||
// copies of the Software, and to permit persons to whom the Software is | ||
// furnished to do so, subject to the following conditions: | ||
// | ||
// The above copyright notice and this permission notice shall be included in | ||
// all copies or substantial portions of the Software. | ||
// | ||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN | ||
// THE SOFTWARE. | ||
|
||
package model | ||
|
||
import ( | ||
"testing" | ||
"time" | ||
|
||
"github.com/stretchr/testify/assert" | ||
) | ||
|
||
var ( | ||
currTime = time.Now() | ||
) | ||
|
||
func TestSortTraces(t *testing.T) { | ||
t1 := &Trace{ | ||
Spans: []*Span{ | ||
{ | ||
TraceID: TraceID{Low: 1}, | ||
SpanID: SpanID(2), | ||
Tags: []KeyValue{{Key: "world"}, {Key: "hello"}}, | ||
Process: &Process{ | ||
ServiceName: "hello", | ||
Tags: []KeyValue{{Key: "hello"}, {Key: "world"}}, | ||
}, | ||
}, | ||
{ | ||
TraceID: TraceID{Low: 1}, | ||
SpanID: SpanID(1), | ||
Logs: []Log{ | ||
{ | ||
Timestamp: currTime, | ||
Fields: []KeyValue{{Key: "world"}, {Key: "hello"}}, | ||
}, | ||
{ | ||
Timestamp: currTime.Add(-time.Hour), | ||
Fields: []KeyValue{{Key: "hello"}, {Key: "world"}}, | ||
}, | ||
}, | ||
}, | ||
}, | ||
} | ||
t2 := &Trace{ | ||
Spans: []*Span{ | ||
{ | ||
TraceID: TraceID{Low: 1}, | ||
SpanID: SpanID(2), | ||
Tags: []KeyValue{{Key: "world"}, {Key: "hello"}}, | ||
Process: &Process{ | ||
ServiceName: "hello", | ||
Tags: []KeyValue{{Key: "hello"}, {Key: "world"}}, | ||
}, | ||
}, | ||
{ | ||
TraceID: TraceID{Low: 1}, | ||
SpanID: SpanID(1), | ||
Logs: []Log{ | ||
{ | ||
Timestamp: currTime.Add(-time.Hour), | ||
Fields: []KeyValue{{Key: "world"}, {Key: "hello"}}, | ||
}, | ||
{ | ||
Timestamp: currTime, | ||
Fields: []KeyValue{{Key: "hello"}, {Key: "world"}}, | ||
}, | ||
}, | ||
}, | ||
}, | ||
} | ||
SortTrace(t1) | ||
SortTrace(t2) | ||
assert.EqualValues(t, t1, t2) | ||
} | ||
|
||
func TestSortListOfTraces(t *testing.T) { | ||
t1 := &Trace{ | ||
Spans: []*Span{ | ||
{ | ||
TraceID: TraceID{Low: 1}, | ||
}, | ||
{ | ||
TraceID: TraceID{Low: 1}, | ||
}, | ||
}, | ||
} | ||
t2 := &Trace{ | ||
Spans: []*Span{ | ||
{ | ||
TraceID: TraceID{Low: 2}, | ||
}, | ||
}, | ||
} | ||
t3 := &Trace{ | ||
Spans: []*Span{ | ||
{ | ||
TraceID: TraceID{Low: 3}, | ||
}, | ||
}, | ||
} | ||
t4 := &Trace{} | ||
|
||
list1 := []*Trace{t1, t4, t2, t3} | ||
list2 := []*Trace{t4, t2, t1, t3} | ||
SortTraces(list1) | ||
SortTraces(list2) | ||
assert.EqualValues(t, list1, list2) | ||
} |
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
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
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,80 @@ | ||
// Copyright (c) 2017 Uber Technologies, Inc. | ||
// | ||
// Permission is hereby granted, free of charge, to any person obtaining a copy | ||
// of this software and associated documentation files (the "Software"), to deal | ||
// in the Software without restriction, including without limitation the rights | ||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | ||
// copies of the Software, and to permit persons to whom the Software is | ||
// furnished to do so, subject to the following conditions: | ||
// | ||
// The above copyright notice and this permission notice shall be included in | ||
// all copies or substantial portions of the Software. | ||
// | ||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN | ||
// THE SOFTWARE. | ||
|
||
package integration | ||
|
||
import ( | ||
"encoding/json" | ||
"testing" | ||
|
||
"github.com/kr/pretty" | ||
"github.com/stretchr/testify/assert" | ||
"github.com/stretchr/testify/require" | ||
|
||
"github.com/uber/jaeger/model" | ||
) | ||
|
||
func CompareSliceOfTraces(t *testing.T, expected []*model.Trace, actual []*model.Trace) { | ||
require.Equal(t, len(expected), len(actual)) | ||
model.SortTraces(expected) | ||
model.SortTraces(actual) | ||
for i := range expected { | ||
checkSize(t, expected[i], actual[i]) | ||
} | ||
if !assert.EqualValues(t, expected, actual) { | ||
for _, err := range pretty.Diff(expected, actual) { | ||
t.Log(err) | ||
} | ||
out, err := json.Marshal(actual) | ||
assert.NoError(t, err) | ||
t.Logf("Actual traces: %s", string(out)) | ||
} | ||
} | ||
|
||
func CompareTraces(t *testing.T, expected *model.Trace, actual *model.Trace) { | ||
if expected.Spans == nil { | ||
require.Nil(t, actual.Spans) | ||
return | ||
} | ||
model.SortTrace(expected) | ||
model.SortTrace(actual) | ||
checkSize(t, expected, actual) | ||
if !assert.EqualValues(t, expected, actual) { | ||
for _, err := range pretty.Diff(expected, actual) { | ||
t.Log(err) | ||
} | ||
out, err := json.Marshal(actual) | ||
assert.NoError(t, err) | ||
t.Logf("Actual trace: %s", string(out)) | ||
} | ||
} | ||
|
||
func checkSize(t *testing.T, expected *model.Trace, actual *model.Trace) { | ||
require.True(t, len(expected.Spans) == len(actual.Spans)) | ||
for i := range expected.Spans { | ||
expectedSpan := expected.Spans[i] | ||
actualSpan := actual.Spans[i] | ||
require.True(t, len(expectedSpan.Tags) == len(actualSpan.Tags)) | ||
require.True(t, len(expectedSpan.Logs) == len(actualSpan.Logs)) | ||
if expectedSpan.Process != nil && actualSpan.Process != nil { | ||
require.True(t, len(expectedSpan.Process.Tags) == len(actualSpan.Process.Tags)) | ||
} | ||
} | ||
} |
Oops, something went wrong.