blob: fb88f26c16b62fb428642e62d873068fadad70be [file] [log] [blame] [edit]
// Package pivot provides the ability to pivot dataframes.
package pivot
import (
"context"
"testing"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"go.skia.org/infra/go/paramtools"
"go.skia.org/infra/perf/go/dataframe"
"go.skia.org/infra/perf/go/types"
)
const badValue = "not a valid choice"
func TestOptionsValid_Valid_ReturnsNil(t *testing.T) {
assert.NoError(t, Request{
GroupBy: []string{"test"},
Operation: Avg,
Summary: []Operation{Avg},
}.Valid())
}
func TestOptionsValid_EmptyGroupBy_ReturnsError(t *testing.T) {
assert.Contains(t, Request{
GroupBy: []string{},
Operation: Avg,
}.Valid().Error(), "GroupBy")
}
func TestOptionsValid_BadOperation_ReturnsError(t *testing.T) {
assert.Contains(t, Request{
GroupBy: []string{"test"},
Operation: Operation(badValue),
}.Valid().Error(), badValue)
}
func TestOptionsValid_BadColumns_ReturnsError(t *testing.T) {
assert.Contains(t, Request{
GroupBy: []string{"test"},
Operation: Avg,
Summary: []Operation{badValue},
}.Valid().Error(), badValue)
}
func TestIntermediateKeyFromFullKey_AllKeysExist_ReturnsCorrectKey(t *testing.T) {
const traceKey = ",arch=arm,config=8888,"
actual := groupKeyFromTraceKey(paramtools.NewParams(traceKey), []string{"arch", "config"})
assert.Equal(t, traceKey, actual)
}
func TestIntermediateKeyFromFullKey_OnlySomeKeysAreSelected_UnselectedKeysAreRemoved(t *testing.T) {
actual := groupKeyFromTraceKey(paramtools.NewParams(",arch=arm,config=8888,device=Nexus7"), []string{"arch", "config"})
assert.Equal(t, ",arch=arm,config=8888,", actual)
}
func TestIntermediateKeyFromFullKey_OneKeyDoesNotExist_ReturnsEmptyString(t *testing.T) {
actual := groupKeyFromTraceKey(paramtools.NewParams(",arch=arm,config=8888,"), []string{"unknown_key"})
assert.Equal(t, "", actual)
}
func TestIntermediateKeyFromFullKey_NoKeys_ReturnsEmptyString(t *testing.T) {
actual := groupKeyFromTraceKey(paramtools.NewParams(",arch=arm,config=8888,"), nil)
assert.Equal(t, "", actual)
}
func dataframeForTesting() *dataframe.DataFrame {
df := dataframe.NewEmpty()
df.TraceSet = types.TraceSet{
",arch=arm,config=8888,device=Nexus5,": types.Trace{1, 0, 0},
",arch=arm,config=565,device=Nexus5,": types.Trace{0, 2, 0},
",arch=arm,config=gles,device=Nexus5,": types.Trace{0, 0, 3},
",arch=intel,config=8888,device=Nexus5,": types.Trace{1, 2, 3},
",arch=intel,config=565,device=Nexus5,": types.Trace{1, 2, 3},
",arch=intel,config=gles,device=Nexus5,": types.Trace{1, 2, 3},
",arch=arm,config=8888,device=Nexus7,": types.Trace{10, 0, 0},
",arch=arm,config=565,device=Nexus7,": types.Trace{0, 20, 0},
",arch=arm,config=gles,device=Nexus7,": types.Trace{0, 0, 30},
",arch=intel,config=8888,device=Nexus7,": types.Trace{10, 20, 30},
",arch=intel,config=565,device=Nexus7,": types.Trace{10, 20, 30},
",arch=intel,config=gles,device=Nexus7,": types.Trace{10, 20, 30},
",this=trace,does=not,match=anykeys,": types.Trace{100, 100, 100},
}
df.Header = []*dataframe.ColumnHeader{}
for i := 0; i < 3; i++ {
df.Header = append(df.Header, &dataframe.ColumnHeader{Offset: types.CommitNumber(i)})
}
df.BuildParamSet()
return df
}
func TestPivot_InvalidRequest_ReturnsError(t *testing.T) {
req := Request{
GroupBy: []string{},
Operation: Operation("not-a-valid-operation"),
}
df := dataframeForTesting()
_, err := Pivot(context.Background(), req, df)
require.Error(t, err)
}
func TestPivot_KeyNotInParamSet_ReturnsError(t *testing.T) {
req := Request{
GroupBy: []string{"unknown_key"},
Operation: Sum,
}
df := dataframeForTesting()
_, err := Pivot(context.Background(), req, df)
require.Error(t, err)
}
func TestPivot_SumOperationNoSummary_Success(t *testing.T) {
req := Request{
GroupBy: []string{"arch", "device"},
Operation: Sum,
}
df := dataframeForTesting()
df, err := Pivot(context.Background(), req, df)
require.NoError(t, err)
require.Equal(t, types.TraceSet{
",arch=arm,device=Nexus5,": types.Trace{1, 2, 3},
",arch=intel,device=Nexus5,": types.Trace{3, 6, 9},
",arch=arm,device=Nexus7,": types.Trace{10, 20, 30},
",arch=intel,device=Nexus7,": types.Trace{30, 60, 90},
}, df.TraceSet)
require.NotEmpty(t, df.ParamSet)
}
func TestPivot_SumOperationNoSummaryExtraKeyInParamSet_GroupsWithNoTracesAreMissingFromResult(t *testing.T) {
req := Request{
GroupBy: []string{"arch"},
Operation: Sum,
}
df := dataframeForTesting()
// Add risc-v as an arch.
df.ParamSet["arch"] = append(df.ParamSet["arch"], "risc-v")
df, err := Pivot(context.Background(), req, df)
require.NoError(t, err)
// Note that risc-v does not appear in result.
require.Equal(t, types.TraceSet{
",arch=arm,": types.Trace{11, 22, 33},
",arch=intel,": types.Trace{33, 66, 99},
}, df.TraceSet)
}
func TestPivot_SumOperationWithSummary_Success(t *testing.T) {
req := Request{
GroupBy: []string{"arch", "device"},
Operation: Sum,
Summary: []Operation{Avg, Sum},
}
df := dataframeForTesting()
df, err := Pivot(context.Background(), req, df)
require.NoError(t, err)
require.Equal(t, types.TraceSet{
",arch=arm,device=Nexus5,": types.Trace{2, 6},
",arch=intel,device=Nexus5,": types.Trace{6, 18},
",arch=arm,device=Nexus7,": types.Trace{20, 60},
",arch=intel,device=Nexus7,": types.Trace{60, 180},
}, df.TraceSet)
require.NotEmpty(t, df.ParamSet)
}
func TestPivot_ContextIsCancelled_ReturnsError(t *testing.T) {
req := Request{
GroupBy: []string{"arch", "device"},
Operation: Sum,
Summary: []Operation{Avg, Sum},
}
df := dataframeForTesting()
ctx, cancel := context.WithCancel(context.Background())
cancel()
_, err := Pivot(ctx, req, df)
require.Contains(t, err.Error(), "canceled")
}