featurebase/server/grpc_test.go
2020-05-15 19:52:03 +02:00

363 lines
8.1 KiB
Go

// Copyright 2017 Pilosa Corp.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package server_test
import (
"context"
"testing"
"github.com/pilosa/pilosa/v2"
pb "github.com/pilosa/pilosa/v2/proto"
"github.com/pilosa/pilosa/v2/server"
"github.com/pilosa/pilosa/v2/test"
"google.golang.org/grpc/codes"
"google.golang.org/grpc/status"
)
func TestGRPC(t *testing.T) {
t.Run("ToTable", func(t *testing.T) {
type expHeader struct {
name string
dataType string
}
type expColumn interface{}
va, vb := int64(-11), int64(-12)
tests := []struct {
result interface{}
expHeaders []expHeader
expColumns [][]expColumn
}{
// Row (uint64)
{
pilosa.NewRow(10, 11, 12),
[]expHeader{
{"_id", "uint64"},
},
[][]expColumn{
{uint64(10)},
{uint64(11)},
{uint64(12)},
},
},
// Row (string)
{
&pilosa.Row{Keys: []string{"ten", "eleven", "twelve"}},
[]expHeader{
{"_id", "string"},
},
[][]expColumn{
{"ten"},
{"eleven"},
{"twelve"},
},
},
// PairField (uint64)
{
pilosa.PairField{
Pair: pilosa.Pair{ID: 10, Count: 123},
Field: "fld",
},
[]expHeader{
{"fld", "uint64"},
{"count", "uint64"},
},
[][]expColumn{
{uint64(10), uint64(123)},
},
},
// Pair (string)
{
pilosa.PairField{
Pair: pilosa.Pair{Key: "ten", Count: 123},
Field: "fld",
},
[]expHeader{
{"fld", "string"},
{"count", "uint64"},
},
[][]expColumn{
{string("ten"), uint64(123)},
},
},
// *PairsField (uint64)
{
&pilosa.PairsField{
Pairs: []pilosa.Pair{
{ID: 10, Count: 123},
{ID: 11, Count: 456},
},
Field: "fld",
},
[]expHeader{
{"fld", "uint64"},
{"count", "uint64"},
},
[][]expColumn{
{uint64(10), uint64(123)},
{uint64(11), uint64(456)},
},
},
// *PairsField (string)
{
&pilosa.PairsField{
Pairs: []pilosa.Pair{
{Key: "ten", Count: 123},
{Key: "eleven", Count: 456},
},
Field: "fld",
},
[]expHeader{
{"fld", "string"},
{"count", "uint64"},
},
[][]expColumn{
{"ten", uint64(123)},
{"eleven", uint64(456)},
},
},
// []GroupCount (uint64)
{
[]pilosa.GroupCount{
pilosa.GroupCount{
Group: []pilosa.FieldRow{
{Field: "a", RowID: 10},
{Field: "b", RowID: 11},
},
Count: 123,
},
pilosa.GroupCount{
Group: []pilosa.FieldRow{
{Field: "a", RowID: 10},
{Field: "b", RowID: 12},
},
Count: 456,
},
pilosa.GroupCount{
Group: []pilosa.FieldRow{
{Field: "va", Value: &va},
{Field: "vb", Value: &vb},
},
Count: 789,
},
},
[]expHeader{
{"a", "uint64"},
{"b", "uint64"},
{"count", "uint64"},
{"sum", "int64"},
},
[][]expColumn{
{uint64(10), uint64(11), uint64(123), int64(0)},
{uint64(10), uint64(12), uint64(456), int64(0)},
{int64(va), int64(vb), uint64(789), int64(0)},
},
},
// []GroupCount (string)
{
[]pilosa.GroupCount{
pilosa.GroupCount{
Group: []pilosa.FieldRow{
{Field: "a", RowKey: "ten"},
{Field: "b", RowKey: "eleven"},
},
Count: 123,
},
{
Group: []pilosa.FieldRow{
{Field: "a", RowKey: "ten"},
{Field: "b", RowKey: "twelve"},
},
Count: 456,
},
},
[]expHeader{
{"a", "string"},
{"b", "string"},
{"count", "uint64"},
{"sum", "int64"},
},
[][]expColumn{
{"ten", "eleven", uint64(123), int64(0)},
{"ten", "twelve", uint64(456), int64(0)},
},
},
// RowIdentifiers (uint64)
{
pilosa.RowIdentifiers{
Rows: []uint64{10, 11, 12},
},
[]expHeader{
{"", "uint64"}, // This is blank because we don't expose RowIdentifiers.field, so we have no way to set it for tests.
},
[][]expColumn{
{uint64(10)},
{uint64(11)},
{uint64(12)},
},
},
// RowIdentifiers (string)
{
pilosa.RowIdentifiers{
Keys: []string{"ten", "eleven", "twelve"},
},
[]expHeader{
{"", "string"}, // This is blank because we don't expose RowIdentifiers.field, so we have no way to set it for tests.
},
[][]expColumn{
{"ten"},
{"eleven"},
{"twelve"},
},
},
// uint64
{
uint64(123),
[]expHeader{
{"count", "uint64"},
},
[][]expColumn{
{uint64(123)},
},
},
// bool
{
true,
[]expHeader{
{"result", "bool"},
},
[][]expColumn{
{true},
},
},
// ValCount
{
pilosa.ValCount{Val: 1, Count: 1},
[]expHeader{{"value", "int64"}, {"count", "int64"}},
[][]expColumn{{int64(1), int64(1)}},
},
{
pilosa.ValCount{FloatVal: 1.24, Count: 1},
[]expHeader{{"value", "float64"}, {"count", "int64"}},
[][]expColumn{{float64(1.24), int64(1)}},
},
// SignedRow
{
pilosa.SignedRow{
Neg: pilosa.NewRow(13, 14, 15),
Pos: pilosa.NewRow(10, 11, 12),
},
[]expHeader{
{"", "int64"},
},
[][]expColumn{
{int64(-15)},
{int64(-14)},
{int64(-13)},
{int64(10)},
{int64(11)},
{int64(12)},
},
},
}
for ti, test := range tests {
toTabler, err := server.ToTablerWrapper(test.result)
if err != nil {
t.Fatal(err)
}
table, err := toTabler.ToTable()
if err != nil {
t.Fatal(err)
}
// Ensure headers match.
for i, header := range table.GetHeaders() {
if header.Name != test.expHeaders[i].name {
t.Fatalf("test %d expected header name: %s, but got: %s", ti, test.expHeaders[i].name, header.Name)
}
if header.Datatype != test.expHeaders[i].dataType {
t.Fatalf("test %d expected header data type: %s, but got: %s", ti, test.expHeaders[i].dataType, header.Datatype)
}
}
// Ensure column data matches.
for i, row := range table.GetRows() {
for j, column := range row.GetColumns() {
switch v := test.expColumns[i][j].(type) {
case string:
val := column.GetStringVal()
if val != v {
t.Fatalf("test %d expected column val: %v, but got: %v", ti, v, val)
}
case uint64:
val := column.GetUint64Val()
if val != v {
t.Fatalf("test %d expected column val: %v, but got: %v", ti, v, val)
}
case bool:
val := column.GetBoolVal()
if val != v {
t.Fatalf("test %d expected column val: %v, but got: %v", ti, v, val)
}
case int64:
val := column.GetInt64Val()
if val != v {
t.Fatalf("test %d expected column val: %v but got: %v", ti, v, val)
}
case float64:
val := column.GetFloat64Val()
if val != v {
t.Fatalf("test %d expected column val: %v but got: %v", ti, v, val)
}
default:
t.Fatalf("test %d has unhandled data type: %T", ti, v)
}
}
}
}
})
}
func TestQueryPQLUnary(t *testing.T) {
m := test.RunCommand(t)
defer m.Close()
i := m.MustCreateIndex(t, "i", pilosa.IndexOptions{})
m.MustCreateField(t, i.Name(), "f", pilosa.OptFieldKeys())
ctx := context.Background()
gh := server.NewGRPCHandler(m.API)
_, err := gh.QueryPQLUnary(ctx, &pb.QueryPQLRequest{
Index: i.Name(),
Pql: `Set(0, f="zero")`,
})
if err != nil {
// Unary query should work
t.Fatal(err)
}
_, err = gh.QueryPQLUnary(ctx, &pb.QueryPQLRequest{
Index: i.Name(),
Pql: `Set(1, f="one") Set(2, f="two")`,
})
staterr := status.Convert(err)
if staterr == nil || staterr.Code() != codes.InvalidArgument {
// QueryPQLUnary handles exactly one query
t.Fatalf("expected error: InvalidArgument, got: %v", err)
}
}