adjust the tests to match the new unexported Field and FrameOptions

This commit is contained in:
Travis Turner 2018-06-01 21:03:18 -05:00
parent d799967fc6
commit dbb4cdf390
No known key found for this signature in database
GPG key ID: 7F08008DFD9314C9
10 changed files with 423 additions and 640 deletions

View file

@ -244,16 +244,17 @@ func TestClient_ImportValue(t *testing.T) {
hldr := test.MustOpenHolder()
defer hldr.Close()
fld := pilosa.Field{
Name: "fld",
Type: pilosa.FieldTypeInt,
fldName := "f"
fo := pilosa.FrameOptions{
Type: pilosa.FrameTypeInt,
Min: -100,
Max: 100,
}
// Load bitmap into cache to ensure cache gets updated.
index := hldr.MustCreateIndexIfNotExists("i", pilosa.IndexOptions{})
frame, err := index.CreateFrameIfNotExists("f", pilosa.FrameOptions{Fields: []*pilosa.Field{&fld}})
frame, err := index.CreateFrameIfNotExists(fldName, fo)
if err != nil {
t.Fatal(err)
}
@ -266,7 +267,7 @@ func TestClient_ImportValue(t *testing.T) {
// Send import request.
c := test.MustNewClient(s.Host(), defaultClient)
if err := c.ImportValue(context.Background(), "i", "f", fld.Name, 0, []pilosa.FieldValue{
if err := c.ImportValue(context.Background(), "i", "f", fldName, 0, []pilosa.FieldValue{
{ColumnID: 1, Value: -10},
{ColumnID: 2, Value: 20},
{ColumnID: 3, Value: 40},
@ -275,7 +276,7 @@ func TestClient_ImportValue(t *testing.T) {
}
// Verify Sum.
sum, cnt, err := frame.FieldSum(nil, fld.Name)
sum, cnt, err := frame.FieldSum(nil, fldName)
if err != nil {
t.Fatal(err)
}
@ -284,7 +285,7 @@ func TestClient_ImportValue(t *testing.T) {
}
// Verify Min.
min, cnt, err := frame.FieldMin(nil, fld.Name)
min, cnt, err := frame.FieldMin(nil, fldName)
if err != nil {
t.Fatal(err)
}
@ -293,11 +294,11 @@ func TestClient_ImportValue(t *testing.T) {
}
// Verify Min with Filter.
filter, err := frame.FieldRange(fld.Name, pql.GT, 40)
filter, err := frame.FieldRange(fldName, pql.GT, 40)
if err != nil {
t.Fatal(err)
}
min, cnt, err = frame.FieldMin(filter, fld.Name)
min, cnt, err = frame.FieldMin(filter, fldName)
if err != nil {
t.Fatal(err)
}
@ -306,7 +307,7 @@ func TestClient_ImportValue(t *testing.T) {
}
// Verify Max.
max, cnt, err := frame.FieldMax(nil, fld.Name)
max, cnt, err := frame.FieldMax(nil, fldName)
if err != nil {
t.Fatal(err)
}

View file

@ -422,24 +422,6 @@ func TestCluster_ResizeStates(t *testing.T) {
tc.SetBit("i", "f", "standard", 1, 101, nil)
tc.SetBit("i", "f", "standard", 1, 1300000, nil)
// Add Field Data to node0.
if err := tc.CreateFrame("i", "fields", FrameOptions{
Fields: []*oField{
{
Name: "fld0",
Type: FieldTypeInt,
Min: -100,
Max: 100,
},
},
}); err != nil {
t.Fatal(err)
}
tc.SetFieldValue("i", "fields", 1, "fld0", -10)
tc.SetFieldValue("i", "fields", 1, "fld0", 10)
tc.SetFieldValue("i", "fields", 1300000, "fld0", -99)
tc.SetFieldValue("i", "fields", 1300000, "fld0", 99)
// Before starting the resize, get the CheckSum to use for
// comparison later.
node0Frame := node0.Holder.Frame("i", "f")
@ -447,11 +429,6 @@ func TestCluster_ResizeStates(t *testing.T) {
node0Fragment := node0View.Fragment(1)
node0Checksum := node0Fragment.Checksum()
node0Frame = node0.Holder.Frame("i", "fields")
node0View = node0Frame.View("field_fld0")
node0Fragment = node0View.Fragment(1)
node0ChecksumFld := node0Fragment.Checksum()
// AddNode needs to block until the resize process has completed.
tc.AddNode(false)
node1 := tc.Clusters[1]
@ -485,17 +462,6 @@ func TestCluster_ResizeStates(t *testing.T) {
t.Fatalf("expected standard view checksum to match: %x - %x", chksum, node0Checksum)
}
// Values
// Verify that node-1 contains the fragment (i/fields/field_fld0/1) transferred from node-0.
node1Frame = node1.Holder.Frame("i", "fields")
node1View = node1Frame.View("field_fld0")
node1Fragment = node1View.Fragment(1)
// Ensure checksums are the same.
if chksum := node1Fragment.Checksum(); !bytes.Equal(chksum, node0ChecksumFld) {
t.Fatalf("expected checksum to match: %x - %x", chksum, node0ChecksumFld)
}
// Close TestCluster.
if err := tc.Close(); err != nil {
t.Fatal(err)

View file

@ -82,6 +82,7 @@ func TestImportCommand_Run(t *testing.T) {
}
}
// TODO: revisit this test once Frame is renamed Field
// Ensure that the ImportValue path runs (note: we have specified a value
// for cm.Field.)
func TestImportCommand_RunValue(t *testing.T) {
@ -107,11 +108,11 @@ func TestImportCommand_RunValue(t *testing.T) {
cm.Host = s.Host()
http.DefaultClient.Do(MustNewHTTPRequest("POST", s.URL+"/index/i", strings.NewReader("")))
http.DefaultClient.Do(MustNewHTTPRequest("POST", s.URL+"/index/i/frame/f", strings.NewReader(`{"options":{"fields": [{"name": "foo", "type": "int", "min": 0, "max": 100}]}}`)))
http.DefaultClient.Do(MustNewHTTPRequest("POST", s.URL+"/index/i/frame/f", strings.NewReader(`{"options":{"type": "int", "min": 0, "max": 100}}`)))
cm.Index = "i"
cm.Frame = "f"
cm.Field = "foo"
cm.Field = "f"
cm.Paths = []string{file.Name()}
err = cm.Run(ctx)
if err != nil {

View file

@ -272,10 +272,9 @@ func TestExecutor_Execute_SetFieldValue(t *testing.T) {
// Create frames.
index := hldr.MustCreateIndexIfNotExists("i", pilosa.IndexOptions{})
if _, err := index.CreateFrameIfNotExists("f", pilosa.FrameOptions{
Fields: []*pilosa.Field{
{Name: "field0", Type: pilosa.FieldTypeInt, Min: 0, Max: 50},
{Name: "field1", Type: pilosa.FieldTypeInt, Min: 1, Max: 2},
},
Type: pilosa.FrameTypeInt,
Min: 0,
Max: 50,
}); err != nil {
t.Fatal(err)
} else if _, err := index.CreateFrameIfNotExists("xxx", pilosa.FrameOptions{}); err != nil {
@ -284,14 +283,14 @@ func TestExecutor_Execute_SetFieldValue(t *testing.T) {
// Set field values.
e := test.NewExecutor(hldr.Holder, test.NewCluster(1))
if _, err := e.Execute(context.Background(), "i", test.MustParse(`SetFieldValue(col=10, frame=f, field0=25, field1=2)`), nil, nil); err != nil {
if _, err := e.Execute(context.Background(), "i", test.MustParse(`SetFieldValue(col=10, frame=f, f=25)`), nil, nil); err != nil {
t.Fatal(err)
} else if _, err := e.Execute(context.Background(), "i", test.MustParse(`SetFieldValue(col=100, frame=f, field0=10)`), nil, nil); err != nil {
} else if _, err := e.Execute(context.Background(), "i", test.MustParse(`SetFieldValue(col=100, frame=f, f=10)`), nil, nil); err != nil {
t.Fatal(err)
}
f := hldr.Frame("i", "f")
if value, exists, err := f.FieldValue(10, "field0"); err != nil {
if value, exists, err := f.FieldValue(10, "f"); err != nil {
t.Fatal(err)
} else if !exists {
t.Fatal("expected value to exist")
@ -299,15 +298,7 @@ func TestExecutor_Execute_SetFieldValue(t *testing.T) {
t.Fatalf("unexpected value: %v", value)
}
if value, exists, err := f.FieldValue(10, "field1"); err != nil {
t.Fatal(err)
} else if !exists {
t.Fatal("expected value to exist")
} else if value != 2 {
t.Fatalf("unexpected value: %v", value)
}
if value, exists, err := f.FieldValue(100, "field0"); err != nil {
if value, exists, err := f.FieldValue(100, "f"); err != nil {
t.Fatal(err)
} else if !exists {
t.Fatal("expected value to exist")
@ -321,37 +312,37 @@ func TestExecutor_Execute_SetFieldValue(t *testing.T) {
defer hldr.Close()
index := hldr.MustCreateIndexIfNotExists("i", pilosa.IndexOptions{})
if _, err := index.CreateFrameIfNotExists("f", pilosa.FrameOptions{
Fields: []*pilosa.Field{
{Name: "field0", Type: pilosa.FieldTypeInt, Min: 0, Max: 100},
},
Type: pilosa.FrameTypeInt,
Min: 0,
Max: 100,
}); err != nil {
t.Fatal(err)
}
t.Run("ErrFrameRequired", func(t *testing.T) {
e := test.NewExecutor(hldr.Holder, test.NewCluster(1))
if _, err := e.Execute(context.Background(), "i", test.MustParse(`SetFieldValue(col=10, field0=100)`), nil, nil); err == nil || err.Error() != `SetFieldValue() frame required` {
if _, err := e.Execute(context.Background(), "i", test.MustParse(`SetFieldValue(col=10, f=100)`), nil, nil); err == nil || err.Error() != `SetFieldValue() frame required` {
t.Fatalf("unexpected error: %s", err)
}
})
t.Run("ErrColumnFieldRequired", func(t *testing.T) {
e := test.NewExecutor(hldr.Holder, test.NewCluster(1))
if _, err := e.Execute(context.Background(), "i", test.MustParse(`SetFieldValue(invalid_column_name=10, frame=f, field0=100)`), nil, nil); err == nil || err.Error() != `SetFieldValue() column field 'col' required` {
if _, err := e.Execute(context.Background(), "i", test.MustParse(`SetFieldValue(invalid_column_name=10, frame=f, f=100)`), nil, nil); err == nil || err.Error() != `SetFieldValue() column field 'col' required` {
t.Fatalf("unexpected error: %s", err)
}
})
t.Run("ErrColumnFieldValue", func(t *testing.T) {
e := test.NewExecutor(hldr.Holder, test.NewCluster(1))
if _, err := e.Execute(context.Background(), "i", test.MustParse(`SetFieldValue(invalid_column_name="bad_column", frame=f, field0=100)`), nil, nil); err == nil || err.Error() != `SetFieldValue() column field 'col' required` {
if _, err := e.Execute(context.Background(), "i", test.MustParse(`SetFieldValue(invalid_column_name="bad_column", frame=f, f=100)`), nil, nil); err == nil || err.Error() != `SetFieldValue() column field 'col' required` {
t.Fatalf("unexpected error: %s", err)
}
})
t.Run("ErrInvalidFieldValueType", func(t *testing.T) {
e := test.NewExecutor(hldr.Holder, test.NewCluster(1))
if _, err := e.Execute(context.Background(), "i", test.MustParse(`SetFieldValue(col=10, frame=f, field0="hello")`), nil, nil); err == nil || err.Error() != `invalid field value type` {
if _, err := e.Execute(context.Background(), "i", test.MustParse(`SetFieldValue(col=10, frame=f, f="hello")`), nil, nil); err == nil || err.Error() != `invalid field value type` {
t.Fatalf("unexpected error: %s", err)
}
})
@ -588,29 +579,33 @@ func TestExecutor_Execute_MinMax(t *testing.T) {
t.Fatal(err)
}
if _, err := idx.CreateFrame("x", pilosa.FrameOptions{}); err != nil {
t.Fatal(err)
}
if _, err := idx.CreateFrame("f", pilosa.FrameOptions{
Fields: []*pilosa.Field{
{Name: "foo", Type: pilosa.FieldTypeInt, Min: -10, Max: 100},
},
Type: pilosa.FrameTypeInt,
Min: -10,
Max: 100,
}); err != nil {
t.Fatal(err)
}
if _, err := e.Execute(context.Background(), "i", test.MustParse(`
SetBit(frame=f, row=0, col=0)
SetBit(frame=f, row=0, col=3)
SetBit(frame=f, row=0, col=`+strconv.Itoa(SliceWidth+1)+`)
SetBit(frame=f, row=1, col=1)
SetBit(frame=f, row=2, col=`+strconv.Itoa(SliceWidth+2)+`)
SetBit(frame=x, row=0, col=0)
SetBit(frame=x, row=0, col=3)
SetBit(frame=x, row=0, col=`+strconv.Itoa(SliceWidth+1)+`)
SetBit(frame=x, row=1, col=1)
SetBit(frame=x, row=2, col=`+strconv.Itoa(SliceWidth+2)+`)
SetFieldValue(frame=f, foo=20, col=0)
SetFieldValue(frame=f, foo=-5, col=1)
SetFieldValue(frame=f, foo=-5, col=2)
SetFieldValue(frame=f, foo=10, col=3)
SetFieldValue(frame=f, foo=30, col=`+strconv.Itoa(SliceWidth)+`)
SetFieldValue(frame=f, foo=40, col=`+strconv.Itoa(SliceWidth+2)+`)
SetFieldValue(frame=f, foo=50, col=`+strconv.Itoa((5*SliceWidth)+100)+`)
SetFieldValue(frame=f, foo=60, col=`+strconv.Itoa(SliceWidth+1)+`)
SetFieldValue(frame=f, f=20, col=0)
SetFieldValue(frame=f, f=-5, col=1)
SetFieldValue(frame=f, f=-5, col=2)
SetFieldValue(frame=f, f=10, col=3)
SetFieldValue(frame=f, f=30, col=`+strconv.Itoa(SliceWidth)+`)
SetFieldValue(frame=f, f=40, col=`+strconv.Itoa(SliceWidth+2)+`)
SetFieldValue(frame=f, f=50, col=`+strconv.Itoa((5*SliceWidth)+100)+`)
SetFieldValue(frame=f, f=60, col=`+strconv.Itoa(SliceWidth+1)+`)
`), nil, nil); err != nil {
t.Fatal(err)
}
@ -622,16 +617,16 @@ func TestExecutor_Execute_MinMax(t *testing.T) {
cnt int64
}{
{filter: ``, exp: -5, cnt: 2},
{filter: `Bitmap(frame=f, row=0)`, exp: 10, cnt: 1},
{filter: `Bitmap(frame=f, row=1)`, exp: -5, cnt: 1},
{filter: `Bitmap(frame=f, row=2)`, exp: 40, cnt: 1},
{filter: `Bitmap(frame=x, row=0)`, exp: 10, cnt: 1},
{filter: `Bitmap(frame=x, row=1)`, exp: -5, cnt: 1},
{filter: `Bitmap(frame=x, row=2)`, exp: 40, cnt: 1},
}
for i, tt := range tests {
var pql string
if tt.filter == "" {
pql = `Min(frame=f, field=foo)`
pql = `Min(frame=f, field=f)`
} else {
pql = fmt.Sprintf(`Min(%s, frame=f, field=foo)`, tt.filter)
pql = fmt.Sprintf(`Min(%s, frame=f, field=f)`, tt.filter)
}
if result, err := e.Execute(context.Background(), "i", test.MustParse(pql), nil, nil); err != nil {
t.Fatal(err)
@ -648,16 +643,16 @@ func TestExecutor_Execute_MinMax(t *testing.T) {
cnt int64
}{
{filter: ``, exp: 60, cnt: 1},
{filter: `Bitmap(frame=f, row=0)`, exp: 60, cnt: 1},
{filter: `Bitmap(frame=f, row=1)`, exp: -5, cnt: 1},
{filter: `Bitmap(frame=f, row=2)`, exp: 40, cnt: 1},
{filter: `Bitmap(frame=x, row=0)`, exp: 60, cnt: 1},
{filter: `Bitmap(frame=x, row=1)`, exp: -5, cnt: 1},
{filter: `Bitmap(frame=x, row=2)`, exp: 40, cnt: 1},
}
for i, tt := range tests {
var pql string
if tt.filter == "" {
pql = `Max(frame=f, field=foo)`
pql = `Max(frame=f, field=f)`
} else {
pql = fmt.Sprintf(`Max(%s, frame=f, field=foo)`, tt.filter)
pql = fmt.Sprintf(`Max(%s, frame=f, field=f)`, tt.filter)
}
if result, err := e.Execute(context.Background(), "i", test.MustParse(pql), nil, nil); err != nil {
t.Fatal(err)
@ -679,39 +674,51 @@ func TestExecutor_Execute_Sum(t *testing.T) {
t.Fatal(err)
}
if _, err := idx.CreateFrame("f", pilosa.FrameOptions{
Fields: []*pilosa.Field{
{Name: "foo", Type: pilosa.FieldTypeInt, Min: 10, Max: 100},
{Name: "bar", Type: pilosa.FieldTypeInt, Min: 0, Max: 100000},
},
if _, err := idx.CreateFrame("x", pilosa.FrameOptions{}); err != nil {
t.Fatal(err)
}
if _, err := idx.CreateFrame("foo", pilosa.FrameOptions{
Type: pilosa.FrameTypeInt,
Min: 10,
Max: 100,
}); err != nil {
t.Fatal(err)
}
if _, err := idx.CreateFrame("bar", pilosa.FrameOptions{
Type: pilosa.FrameTypeInt,
Min: 0,
Max: 100000,
}); err != nil {
t.Fatal(err)
}
if _, err := idx.CreateFrame("other", pilosa.FrameOptions{
Fields: []*pilosa.Field{
{Name: "foo", Type: pilosa.FieldTypeInt, Min: 0, Max: 1000},
},
Type: pilosa.FrameTypeInt,
Min: 0,
Max: 1000,
}); err != nil {
t.Fatal(err)
}
if _, err := e.Execute(context.Background(), "i", test.MustParse(`
SetBit(frame=f, row=0, col=0)
SetBit(frame=f, row=0, col=`+strconv.Itoa(SliceWidth+1)+`)
SetBit(frame=x, row=0, col=0)
SetBit(frame=x, row=0, col=`+strconv.Itoa(SliceWidth+1)+`)
SetFieldValue(frame=f, foo=20, bar=2000, col=0)
SetFieldValue(frame=f, foo=30, col=`+strconv.Itoa(SliceWidth)+`)
SetFieldValue(frame=f, foo=40, col=`+strconv.Itoa(SliceWidth+2)+`)
SetFieldValue(frame=f, foo=50, col=`+strconv.Itoa((5*SliceWidth)+100)+`)
SetFieldValue(frame=f, foo=60, col=`+strconv.Itoa(SliceWidth+1)+`)
SetFieldValue(frame=other, foo=1000, col=0)
SetFieldValue(frame=foo, foo=20, col=0)
SetFieldValue(frame=bar, bar=2000, col=0)
SetFieldValue(frame=foo, foo=30, col=`+strconv.Itoa(SliceWidth)+`)
SetFieldValue(frame=foo, foo=40, col=`+strconv.Itoa(SliceWidth+2)+`)
SetFieldValue(frame=foo, foo=50, col=`+strconv.Itoa((5*SliceWidth)+100)+`)
SetFieldValue(frame=foo, foo=60, col=`+strconv.Itoa(SliceWidth+1)+`)
SetFieldValue(frame=other, other=1000, col=0)
`), nil, nil); err != nil {
t.Fatal(err)
}
t.Run("NoFilter", func(t *testing.T) {
if result, err := e.Execute(context.Background(), "i", test.MustParse(`Sum(frame=f, field=foo)`), nil, nil); err != nil {
if result, err := e.Execute(context.Background(), "i", test.MustParse(`Sum(frame=foo, field=foo)`), nil, nil); err != nil {
t.Fatal(err)
} else if !reflect.DeepEqual(result[0], pilosa.ValCount{Val: 200, Count: 5}) {
t.Fatalf("unexpected result: %s", spew.Sdump(result))
@ -719,7 +726,7 @@ func TestExecutor_Execute_Sum(t *testing.T) {
})
t.Run("WithFilter", func(t *testing.T) {
if result, err := e.Execute(context.Background(), "i", test.MustParse(`Sum(Bitmap(frame=f, row=0), frame=f, field=foo)`), nil, nil); err != nil {
if result, err := e.Execute(context.Background(), "i", test.MustParse(`Sum(Bitmap(frame=x, row=0), frame=foo, field=foo)`), nil, nil); err != nil {
t.Fatal(err)
} else if !reflect.DeepEqual(result[0], pilosa.ValCount{Val: 80, Count: 2}) {
t.Fatalf("unexpected result: %s", spew.Sdump(result))
@ -738,6 +745,7 @@ func TestExecutor_Execute_Range(t *testing.T) {
// Create frame.
if _, err := index.CreateFrameIfNotExists("f", pilosa.FrameOptions{
Type: pilosa.FrameTypeTime,
TimeQuantum: pilosa.TimeQuantum("YMDH"),
}); err != nil {
t.Fatal(err)
@ -766,7 +774,6 @@ func TestExecutor_Execute_Range(t *testing.T) {
t.Fatalf("unexpected columns: %+v", columns)
}
})
}
// Ensure a Range(field) query can be executed.
@ -780,27 +787,38 @@ func TestExecutor_Execute_FieldRange(t *testing.T) {
t.Fatal(err)
}
if _, err := idx.CreateFrame("f", pilosa.FrameOptions{
Fields: []*pilosa.Field{
{Name: "foo", Type: pilosa.FieldTypeInt, Min: 10, Max: 100},
{Name: "bar", Type: pilosa.FieldTypeInt, Min: 0, Max: 100000},
},
if _, err := idx.CreateFrame("f", pilosa.FrameOptions{}); err != nil {
t.Fatal(err)
}
if _, err := idx.CreateFrame("foo", pilosa.FrameOptions{
Type: pilosa.FrameTypeInt,
Min: 10,
Max: 100,
}); err != nil {
t.Fatal(err)
}
if _, err := idx.CreateFrame("bar", pilosa.FrameOptions{
Type: pilosa.FrameTypeInt,
Min: 0,
Max: 100000,
}); err != nil {
t.Fatal(err)
}
if _, err := idx.CreateFrame("other", pilosa.FrameOptions{
Fields: []*pilosa.Field{
{Name: "foo", Type: pilosa.FieldTypeInt, Min: 0, Max: 1000},
},
Type: pilosa.FrameTypeInt,
Min: 0,
Max: 1000,
}); err != nil {
t.Fatal(err)
}
if _, err := idx.CreateFrame("edge", pilosa.FrameOptions{
Fields: []*pilosa.Field{
{Name: "foo", Type: pilosa.FieldTypeInt, Min: -100, Max: 100},
},
Type: pilosa.FrameTypeInt,
Min: -100,
Max: 100,
}); err != nil {
t.Fatal(err)
}
@ -809,20 +827,21 @@ func TestExecutor_Execute_FieldRange(t *testing.T) {
SetBit(frame=f, row=0, col=0)
SetBit(frame=f, row=0, col=`+strconv.Itoa(SliceWidth+1)+`)
SetFieldValue(frame=f, foo=20, bar=2000, col=50)
SetFieldValue(frame=f, foo=30, col=`+strconv.Itoa(SliceWidth)+`)
SetFieldValue(frame=f, foo=10, col=`+strconv.Itoa(SliceWidth+2)+`)
SetFieldValue(frame=f, foo=20, col=`+strconv.Itoa((5*SliceWidth)+100)+`)
SetFieldValue(frame=f, foo=60, col=`+strconv.Itoa(SliceWidth+1)+`)
SetFieldValue(frame=other, foo=1000, col=0)
SetFieldValue(frame=edge, foo=100, col=0)
SetFieldValue(frame=edge, foo=-100, col=1)
SetFieldValue(frame=foo, foo=20, col=50)
SetFieldValue(frame=bar, bar=2000, col=50)
SetFieldValue(frame=foo, foo=30, col=`+strconv.Itoa(SliceWidth)+`)
SetFieldValue(frame=foo, foo=10, col=`+strconv.Itoa(SliceWidth+2)+`)
SetFieldValue(frame=foo, foo=20, col=`+strconv.Itoa((5*SliceWidth)+100)+`)
SetFieldValue(frame=foo, foo=60, col=`+strconv.Itoa(SliceWidth+1)+`)
SetFieldValue(frame=other, other=1000, col=0)
SetFieldValue(frame=edge, edge=100, col=0)
SetFieldValue(frame=edge, edge=-100, col=1)
`), nil, nil); err != nil {
t.Fatal(err)
}
t.Run("EQ", func(t *testing.T) {
if result, err := e.Execute(context.Background(), "i", test.MustParse(`Range(frame=f, foo == 20)`), nil, nil); err != nil {
if result, err := e.Execute(context.Background(), "i", test.MustParse(`Range(frame=foo, foo == 20)`), nil, nil); err != nil {
t.Fatal(err)
} else if !reflect.DeepEqual([]uint64{50, (5 * SliceWidth) + 100}, result[0].(*pilosa.Row).Columns()) {
t.Fatalf("unexpected result: %s", spew.Sdump(result))
@ -831,19 +850,19 @@ func TestExecutor_Execute_FieldRange(t *testing.T) {
t.Run("NEQ", func(t *testing.T) {
// NEQ null
if result, err := e.Execute(context.Background(), "i", test.MustParse(`Range(frame=other, foo != null)`), nil, nil); err != nil {
if result, err := e.Execute(context.Background(), "i", test.MustParse(`Range(frame=other, other != null)`), nil, nil); err != nil {
t.Fatal(err)
} else if !reflect.DeepEqual([]uint64{0}, result[0].(*pilosa.Row).Columns()) {
t.Fatalf("unexpected result: %s", spew.Sdump(result))
}
// NEQ <int>
if result, err := e.Execute(context.Background(), "i", test.MustParse(`Range(frame=f, foo != 20)`), nil, nil); err != nil {
if result, err := e.Execute(context.Background(), "i", test.MustParse(`Range(frame=foo, foo != 20)`), nil, nil); err != nil {
t.Fatal(err)
} else if !reflect.DeepEqual([]uint64{SliceWidth, SliceWidth + 1, SliceWidth + 2}, result[0].(*pilosa.Row).Columns()) {
t.Fatalf("unexpected result: %s", spew.Sdump(result))
}
// NEQ -<int>
if result, err := e.Execute(context.Background(), "i", test.MustParse(`Range(frame=other, foo != -20)`), nil, nil); err != nil {
if result, err := e.Execute(context.Background(), "i", test.MustParse(`Range(frame=other, other != -20)`), nil, nil); err != nil {
t.Fatal(err)
} else if !reflect.DeepEqual([]uint64{0}, result[0].(*pilosa.Row).Columns()) {
//t.Fatalf("unexpected result: %s", spew.Sdump(result))
@ -852,7 +871,7 @@ func TestExecutor_Execute_FieldRange(t *testing.T) {
})
t.Run("LT", func(t *testing.T) {
if result, err := e.Execute(context.Background(), "i", test.MustParse(`Range(frame=f, foo < 20)`), nil, nil); err != nil {
if result, err := e.Execute(context.Background(), "i", test.MustParse(`Range(frame=foo, foo < 20)`), nil, nil); err != nil {
t.Fatal(err)
} else if !reflect.DeepEqual([]uint64{SliceWidth + 2}, result[0].(*pilosa.Row).Columns()) {
t.Fatalf("unexpected result: %s", spew.Sdump(result))
@ -860,7 +879,7 @@ func TestExecutor_Execute_FieldRange(t *testing.T) {
})
t.Run("LTE", func(t *testing.T) {
if result, err := e.Execute(context.Background(), "i", test.MustParse(`Range(frame=f, foo <= 20)`), nil, nil); err != nil {
if result, err := e.Execute(context.Background(), "i", test.MustParse(`Range(frame=foo, foo <= 20)`), nil, nil); err != nil {
t.Fatal(err)
} else if !reflect.DeepEqual([]uint64{50, SliceWidth + 2, (5 * SliceWidth) + 100}, result[0].(*pilosa.Row).Columns()) {
t.Fatalf("unexpected result: %s", spew.Sdump(result))
@ -868,7 +887,7 @@ func TestExecutor_Execute_FieldRange(t *testing.T) {
})
t.Run("GT", func(t *testing.T) {
if result, err := e.Execute(context.Background(), "i", test.MustParse(`Range(frame=f, foo > 20)`), nil, nil); err != nil {
if result, err := e.Execute(context.Background(), "i", test.MustParse(`Range(frame=foo, foo > 20)`), nil, nil); err != nil {
t.Fatal(err)
} else if !reflect.DeepEqual([]uint64{SliceWidth, SliceWidth + 1}, result[0].(*pilosa.Row).Columns()) {
t.Fatalf("unexpected result: %s", spew.Sdump(result))
@ -876,7 +895,7 @@ func TestExecutor_Execute_FieldRange(t *testing.T) {
})
t.Run("GTE", func(t *testing.T) {
if result, err := e.Execute(context.Background(), "i", test.MustParse(`Range(frame=f, foo >= 20)`), nil, nil); err != nil {
if result, err := e.Execute(context.Background(), "i", test.MustParse(`Range(frame=foo, foo >= 20)`), nil, nil); err != nil {
t.Fatal(err)
} else if !reflect.DeepEqual([]uint64{50, SliceWidth, SliceWidth + 1, (5 * SliceWidth) + 100}, result[0].(*pilosa.Row).Columns()) {
t.Fatalf("unexpected result: %s", spew.Sdump(result))
@ -884,7 +903,7 @@ func TestExecutor_Execute_FieldRange(t *testing.T) {
})
t.Run("BETWEEN", func(t *testing.T) {
if result, err := e.Execute(context.Background(), "i", test.MustParse(`Range(frame=other, foo >< [1, 1000])`), nil, nil); err != nil {
if result, err := e.Execute(context.Background(), "i", test.MustParse(`Range(frame=other, other >< [1, 1000])`), nil, nil); err != nil {
t.Fatal(err)
} else if !reflect.DeepEqual([]uint64{0}, result[0].(*pilosa.Row).Columns()) {
t.Fatalf("unexpected result: %s", spew.Sdump(result))
@ -893,7 +912,7 @@ func TestExecutor_Execute_FieldRange(t *testing.T) {
// Ensure that the FieldNotNull code path gets run.
t.Run("FieldNotNull", func(t *testing.T) {
if result, err := e.Execute(context.Background(), "i", test.MustParse(`Range(frame=other, foo >< [0, 1000])`), nil, nil); err != nil {
if result, err := e.Execute(context.Background(), "i", test.MustParse(`Range(frame=other, other >< [0, 1000])`), nil, nil); err != nil {
t.Fatal(err)
} else if !reflect.DeepEqual([]uint64{0}, result[0].(*pilosa.Row).Columns()) {
t.Fatalf("unexpected result: %s", spew.Sdump(result))
@ -901,7 +920,7 @@ func TestExecutor_Execute_FieldRange(t *testing.T) {
})
t.Run("BelowMin", func(t *testing.T) {
if result, err := e.Execute(context.Background(), "i", test.MustParse(`Range(frame=f, foo == 0)`), nil, nil); err != nil {
if result, err := e.Execute(context.Background(), "i", test.MustParse(`Range(frame=foo, foo == 0)`), nil, nil); err != nil {
t.Fatal(err)
} else if !reflect.DeepEqual([]uint64{}, result[0].(*pilosa.Row).Columns()) {
t.Fatalf("unexpected result: %s", spew.Sdump(result))
@ -909,7 +928,7 @@ func TestExecutor_Execute_FieldRange(t *testing.T) {
})
t.Run("AboveMax", func(t *testing.T) {
if result, err := e.Execute(context.Background(), "i", test.MustParse(`Range(frame=f, foo == 200)`), nil, nil); err != nil {
if result, err := e.Execute(context.Background(), "i", test.MustParse(`Range(frame=foo, foo == 200)`), nil, nil); err != nil {
t.Fatal(err)
} else if !reflect.DeepEqual([]uint64{}, result[0].(*pilosa.Row).Columns()) {
t.Fatalf("unexpected result: %s", spew.Sdump(result))
@ -917,7 +936,7 @@ func TestExecutor_Execute_FieldRange(t *testing.T) {
})
t.Run("LTAboveMax", func(t *testing.T) {
if result, err := e.Execute(context.Background(), "i", test.MustParse(`Range(frame=edge, foo < 200)`), nil, nil); err != nil {
if result, err := e.Execute(context.Background(), "i", test.MustParse(`Range(frame=edge, edge < 200)`), nil, nil); err != nil {
t.Fatal(err)
} else if !reflect.DeepEqual([]uint64{0, 1}, result[0].(*pilosa.Row).Columns()) {
t.Fatalf("unexpected result: %s", spew.Sdump(result[0].(*pilosa.Row).Columns()))
@ -925,7 +944,7 @@ func TestExecutor_Execute_FieldRange(t *testing.T) {
})
t.Run("GTBelowMin", func(t *testing.T) {
if result, err := e.Execute(context.Background(), "i", test.MustParse(`Range(frame=edge, foo > -200)`), nil, nil); err != nil {
if result, err := e.Execute(context.Background(), "i", test.MustParse(`Range(frame=edge, edge > -200)`), nil, nil); err != nil {
t.Fatal(err)
} else if !reflect.DeepEqual([]uint64{0, 1}, result[0].(*pilosa.Row).Columns()) {
t.Fatalf("unexpected result: %s", spew.Sdump(result[0].(*pilosa.Row).Columns()))
@ -939,7 +958,7 @@ func TestExecutor_Execute_FieldRange(t *testing.T) {
})
t.Run("ErrFieldNotFound", func(t *testing.T) {
if _, err := e.Execute(context.Background(), "i", test.MustParse(`Range(frame=f, bad_field >= 20)`), nil, nil); err != pilosa.ErrFieldNotFound {
if _, err := e.Execute(context.Background(), "i", test.MustParse(`Range(frame=foo, bad_field >= 20)`), nil, nil); err != pilosa.ErrFieldNotFound {
t.Fatal(err)
}
})

View file

@ -69,14 +69,25 @@ type Frame struct {
Logger Logger
}
// FrameOption is a functional option type for pilosa.Frame.
type FrameOption func(f *Frame) error
// TODO: break these out into separate Options (not a FrameOptions object)
func OptFrameFrameOptions(o FrameOptions) FrameOption {
return func(f *Frame) error {
f.options = o
return nil
}
}
// NewFrame returns a new instance of frame.
func NewFrame(path, index, name string) (*Frame, error) {
func NewFrame(path, index, name string, opts ...FrameOption) (*Frame, error) {
err := ValidateName(name)
if err != nil {
return nil, err
}
return &Frame{
f := &Frame{
path: path,
index: index,
name: name,
@ -95,7 +106,16 @@ func NewFrame(path, index, name string) (*Frame, error) {
},
Logger: NopLogger,
}, nil
}
for _, opt := range opts {
err := opt(f)
if err != nil {
return nil, errors.Wrap(err, "applying option")
}
}
return f, nil
}
// Name returns the name the frame was initialized with.
@ -299,7 +319,7 @@ func (f *Frame) applyOptions(opt FrameOptions) error {
f.options.TimeQuantum = ""
case FrameTypeInt:
f.options.Type = opt.Type
f.options.CacheType = ""
f.options.CacheType = CacheTypeNone
f.options.CacheSize = 0
f.options.Min = opt.Min
f.options.Max = opt.Max
@ -321,7 +341,7 @@ func (f *Frame) applyOptions(opt FrameOptions) error {
}
case FrameTypeTime:
f.options.Type = opt.Type
f.options.CacheType = ""
f.options.CacheType = CacheTypeNone
f.options.CacheSize = 0
f.options.Min = 0
f.options.Max = 0
@ -657,7 +677,7 @@ func (f *Frame) ClearBit(name string, rowID, colID uint64, t *time.Time) (change
// Clear non-time bit.
if v, err := view.ClearBit(rowID, colID); err != nil {
return changed, errors.Wrap(err, "setting on view")
return changed, errors.Wrap(err, "clearing on view")
} else if v {
changed = v
}
@ -675,7 +695,7 @@ func (f *Frame) ClearBit(name string, rowID, colID uint64, t *time.Time) (change
}
if c, err := view.ClearBit(rowID, colID); err != nil {
return changed, errors.Wrapf(err, "setting on view %s", subname)
return changed, errors.Wrapf(err, "clearing on view %s", subname)
} else if c {
changed = true
}
@ -995,7 +1015,7 @@ type FrameOptions struct {
CacheSize uint32 `json:"cacheSize,omitempty"`
Min int64 `json:"min,omitempty"`
Max int64 `json:"max,omitempty"`
TimeQuantum TimeQuantum `json:"timeQuantum,omitempty"` // TODO travis: rename this Quantum?
TimeQuantum TimeQuantum `json:"timeQuantum,omitempty"` // TODO: rename this Quantum?
}
// Validate ensures that FrameOption values are valid.
@ -1064,6 +1084,7 @@ func IsValidFieldType(v string) bool {
}
}
// TODO: finish unexporting this. also, rename it.
// oField represents a range field on a frame.
type oField struct {
Name string `json:"name,omitempty"`

149
frame_internal_test.go Normal file
View file

@ -0,0 +1,149 @@
// 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 pilosa
import (
"reflect"
"testing"
"github.com/pilosa/pilosa/pql"
)
// Ensure a field can adjust to its baseValue.
func TestField_BaseValue(t *testing.T) {
f0 := &oField{
Name: "f0",
Type: FieldTypeInt,
Min: -100,
Max: 900,
}
f1 := &oField{
Name: "f1",
Type: FieldTypeInt,
Min: 0,
Max: 1000,
}
f2 := &oField{
Name: "f2",
Type: FieldTypeInt,
Min: 100,
Max: 1100,
}
t.Run("Normal Condition", func(t *testing.T) {
for _, tt := range []struct {
f *oField
op pql.Token
val int64
expBaseValue uint64
expOutOfRange bool
}{
// LT
{f0, pql.LT, 5, 105, false},
{f0, pql.LT, -8, 92, false},
{f0, pql.LT, -108, 0, true},
{f0, pql.LT, 1005, 1000, false},
{f0, pql.LT, 0, 100, false},
{f1, pql.LT, 5, 5, false},
{f1, pql.LT, -8, 0, true},
{f1, pql.LT, 1005, 1000, false},
{f1, pql.LT, 0, 0, false},
{f2, pql.LT, 5, 0, true},
{f2, pql.LT, -8, 0, true},
{f2, pql.LT, 105, 5, false},
{f2, pql.LT, 1105, 1000, false},
// GT
{f0, pql.GT, -105, 0, false},
{f0, pql.GT, 5, 105, false},
{f0, pql.GT, 905, 0, true},
{f0, pql.GT, 0, 100, false},
{f1, pql.GT, 5, 5, false},
{f1, pql.GT, -8, 0, false},
{f1, pql.GT, 1005, 0, true},
{f1, pql.GT, 0, 0, false},
{f2, pql.GT, 5, 0, false},
{f2, pql.GT, -8, 0, false},
{f2, pql.GT, 105, 5, false},
{f2, pql.GT, 1105, 0, true},
// EQ
{f0, pql.EQ, -105, 0, true},
{f0, pql.EQ, 5, 105, false},
{f0, pql.EQ, 905, 0, true},
{f0, pql.EQ, 0, 100, false},
{f1, pql.EQ, 5, 5, false},
{f1, pql.EQ, -8, 0, true},
{f1, pql.EQ, 1005, 0, true},
{f1, pql.EQ, 0, 0, false},
{f2, pql.EQ, 5, 0, true},
{f2, pql.EQ, -8, 0, true},
{f2, pql.EQ, 105, 5, false},
{f2, pql.EQ, 1105, 0, true},
} {
bv, oor := tt.f.BaseValue(tt.op, tt.val)
if oor != tt.expOutOfRange {
t.Fatalf("baseValue calculation on %s op %s, expected outOfRange %v, got %v", tt.f.Name, tt.op, tt.expOutOfRange, oor)
} else if !reflect.DeepEqual(bv, tt.expBaseValue) {
t.Fatalf("baseValue calculation on %s, expected value %v, got %v", tt.f.Name, tt.expBaseValue, bv)
}
}
})
t.Run("Betwween Condition", func(t *testing.T) {
for _, tt := range []struct {
f *oField
predMin int64
predMax int64
expBaseValueMin uint64
expBaseValueMax uint64
expOutOfRange bool
}{
{f0, -205, -105, 0, 0, true},
{f0, -105, 80, 0, 180, false},
{f0, 5, 20, 105, 120, false},
{f0, 20, 1005, 120, 1000, false},
{f0, 1005, 2000, 0, 0, true},
{f1, -105, -5, 0, 0, true},
{f1, -5, 20, 0, 20, false},
{f1, 5, 20, 5, 20, false},
{f1, 20, 1005, 20, 1000, false},
{f1, 1005, 2000, 0, 0, true},
{f2, 5, 95, 0, 0, true},
{f2, 95, 120, 0, 20, false},
{f2, 105, 120, 5, 20, false},
{f2, 120, 1105, 20, 1000, false},
{f2, 1105, 2000, 0, 0, true},
} {
min, max, oor := tt.f.BaseValueBetween(tt.predMin, tt.predMax)
if oor != tt.expOutOfRange {
t.Fatalf("baseValueBetween calculation on %s, expected outOfRange %v, got %v", tt.f.Name, tt.expOutOfRange, oor)
} else if !reflect.DeepEqual(min, tt.expBaseValueMin) || !reflect.DeepEqual(max, tt.expBaseValueMax) {
t.Fatalf("baseValueBetween calculation on %s, expected min/max %v/%v, got %v/%v", tt.f.Name, tt.expBaseValueMin, tt.expBaseValueMax, min, max)
}
}
})
}

View file

@ -16,11 +16,9 @@ package pilosa_test
import (
"io/ioutil"
"reflect"
"testing"
"github.com/pilosa/pilosa"
"github.com/pilosa/pilosa/pql"
"github.com/pilosa/pilosa/test"
)
@ -52,7 +50,10 @@ func TestFrame_CreateViewIfNotExists(t *testing.T) {
// Ensure frame can set its time quantum.
func TestFrame_SetTimeQuantum(t *testing.T) {
f := test.MustOpenFrame()
fo := pilosa.FrameOptions{
Type: "time",
}
f := test.MustOpenFrame(pilosa.OptFrameFrameOptions(fo))
defer f.Close()
// Set & retrieve time quantum.
@ -77,31 +78,23 @@ func TestFrame_SetFieldValue(t *testing.T) {
defer idx.Close()
f, err := idx.CreateFrame("f", pilosa.FrameOptions{
Fields: []*pilosa.Field{
{Name: "field0", Type: pilosa.FieldTypeInt, Min: 0, Max: 30},
{Name: "field1", Type: pilosa.FieldTypeInt, Min: 20, Max: 25},
},
Type: pilosa.FrameTypeInt,
Min: 0,
Max: 30,
})
if err != nil {
t.Fatal(err)
}
// Set value on first field.
if changed, err := f.SetFieldValue(100, "field0", 21); err != nil {
t.Fatal(err)
} else if !changed {
t.Fatal("expected change")
}
// Set value on same column but different field.
if changed, err := f.SetFieldValue(100, "field1", 25); err != nil {
// Set value on field.
if changed, err := f.SetFieldValue(100, "f", 21); err != nil {
t.Fatal(err)
} else if !changed {
t.Fatal("expected change")
}
// Read value.
if value, exists, err := f.FieldValue(100, "field0"); err != nil {
if value, exists, err := f.FieldValue(100, "f"); err != nil {
t.Fatal(err)
} else if value != 21 {
t.Fatalf("unexpected value: %d", value)
@ -110,7 +103,7 @@ func TestFrame_SetFieldValue(t *testing.T) {
}
// Setting value should return no change.
if changed, err := f.SetFieldValue(100, "field0", 21); err != nil {
if changed, err := f.SetFieldValue(100, "f", 21); err != nil {
t.Fatal(err)
} else if changed {
t.Fatal("expected no change")
@ -122,30 +115,30 @@ func TestFrame_SetFieldValue(t *testing.T) {
defer idx.Close()
f, err := idx.CreateFrame("f", pilosa.FrameOptions{
Fields: []*pilosa.Field{
{Name: "field0", Type: pilosa.FieldTypeInt, Min: 0, Max: 30},
},
Type: pilosa.FrameTypeInt,
Min: 0,
Max: 30,
})
if err != nil {
t.Fatal(err)
}
// Set value.
if changed, err := f.SetFieldValue(100, "field0", 21); err != nil {
if changed, err := f.SetFieldValue(100, "f", 21); err != nil {
t.Fatal(err)
} else if !changed {
t.Fatal("expected change")
}
// Set different value.
if changed, err := f.SetFieldValue(100, "field0", 23); err != nil {
if changed, err := f.SetFieldValue(100, "f", 23); err != nil {
t.Fatal(err)
} else if !changed {
t.Fatal("expected change")
}
// Read value.
if value, exists, err := f.FieldValue(100, "field0"); err != nil {
if value, exists, err := f.FieldValue(100, "f"); err != nil {
t.Fatal(err)
} else if value != 23 {
t.Fatalf("unexpected value: %d", value)
@ -159,9 +152,9 @@ func TestFrame_SetFieldValue(t *testing.T) {
defer idx.Close()
f, err := idx.CreateFrame("f", pilosa.FrameOptions{
Fields: []*pilosa.Field{
{Name: "field0", Type: pilosa.FieldTypeInt, Min: 0, Max: 30},
},
Type: pilosa.FrameTypeInt,
Min: 0,
Max: 30,
})
if err != nil {
t.Fatal(err)
@ -178,16 +171,16 @@ func TestFrame_SetFieldValue(t *testing.T) {
defer idx.Close()
f, err := idx.CreateFrame("f", pilosa.FrameOptions{
Fields: []*pilosa.Field{
{Name: "field0", Type: pilosa.FieldTypeInt, Min: 20, Max: 30},
},
Type: pilosa.FrameTypeInt,
Min: 20,
Max: 30,
})
if err != nil {
t.Fatal(err)
}
// Set value.
if _, err := f.SetFieldValue(100, "field0", 15); err != pilosa.ErrFieldValueTooLow {
if _, err := f.SetFieldValue(100, "f", 15); err != pilosa.ErrFieldValueTooLow {
t.Fatalf("unexpected error: %s", err)
}
})
@ -197,16 +190,16 @@ func TestFrame_SetFieldValue(t *testing.T) {
defer idx.Close()
f, err := idx.CreateFrame("f", pilosa.FrameOptions{
Fields: []*pilosa.Field{
{Name: "field0", Type: pilosa.FieldTypeInt, Min: 20, Max: 30},
},
Type: pilosa.FrameTypeInt,
Min: 20,
Max: 30,
})
if err != nil {
t.Fatal(err)
}
// Set value.
if _, err := f.SetFieldValue(100, "field0", 31); err != pilosa.ErrFieldValueTooHigh {
if _, err := f.SetFieldValue(100, "f", 31); err != pilosa.ErrFieldValueTooHigh {
t.Fatalf("unexpected error: %s", err)
}
})
@ -294,130 +287,3 @@ func TestFrame_DeleteView(t *testing.T) {
t.Fatal("failed to create new view")
}
}
// Ensure a field can adjust to its baseValue.
func TestField_BaseValue(t *testing.T) {
f0 := &pilosa.Field{
Name: "f0",
Type: pilosa.FieldTypeInt,
Min: -100,
Max: 900,
}
f1 := &pilosa.Field{
Name: "f1",
Type: pilosa.FieldTypeInt,
Min: 0,
Max: 1000,
}
f2 := &pilosa.Field{
Name: "f2",
Type: pilosa.FieldTypeInt,
Min: 100,
Max: 1100,
}
t.Run("Normal Condition", func(t *testing.T) {
for _, tt := range []struct {
f *pilosa.Field
op pql.Token
val int64
expBaseValue uint64
expOutOfRange bool
}{
// LT
{f0, pql.LT, 5, 105, false},
{f0, pql.LT, -8, 92, false},
{f0, pql.LT, -108, 0, true},
{f0, pql.LT, 1005, 1000, false},
{f0, pql.LT, 0, 100, false},
{f1, pql.LT, 5, 5, false},
{f1, pql.LT, -8, 0, true},
{f1, pql.LT, 1005, 1000, false},
{f1, pql.LT, 0, 0, false},
{f2, pql.LT, 5, 0, true},
{f2, pql.LT, -8, 0, true},
{f2, pql.LT, 105, 5, false},
{f2, pql.LT, 1105, 1000, false},
// GT
{f0, pql.GT, -105, 0, false},
{f0, pql.GT, 5, 105, false},
{f0, pql.GT, 905, 0, true},
{f0, pql.GT, 0, 100, false},
{f1, pql.GT, 5, 5, false},
{f1, pql.GT, -8, 0, false},
{f1, pql.GT, 1005, 0, true},
{f1, pql.GT, 0, 0, false},
{f2, pql.GT, 5, 0, false},
{f2, pql.GT, -8, 0, false},
{f2, pql.GT, 105, 5, false},
{f2, pql.GT, 1105, 0, true},
// EQ
{f0, pql.EQ, -105, 0, true},
{f0, pql.EQ, 5, 105, false},
{f0, pql.EQ, 905, 0, true},
{f0, pql.EQ, 0, 100, false},
{f1, pql.EQ, 5, 5, false},
{f1, pql.EQ, -8, 0, true},
{f1, pql.EQ, 1005, 0, true},
{f1, pql.EQ, 0, 0, false},
{f2, pql.EQ, 5, 0, true},
{f2, pql.EQ, -8, 0, true},
{f2, pql.EQ, 105, 5, false},
{f2, pql.EQ, 1105, 0, true},
} {
bv, oor := tt.f.BaseValue(tt.op, tt.val)
if oor != tt.expOutOfRange {
t.Fatalf("baseValue calculation on %s op %s, expected outOfRange %v, got %v", tt.f.Name, tt.op, tt.expOutOfRange, oor)
} else if !reflect.DeepEqual(bv, tt.expBaseValue) {
t.Fatalf("baseValue calculation on %s, expected value %v, got %v", tt.f.Name, tt.expBaseValue, bv)
}
}
})
t.Run("Betwween Condition", func(t *testing.T) {
for _, tt := range []struct {
f *pilosa.Field
predMin int64
predMax int64
expBaseValueMin uint64
expBaseValueMax uint64
expOutOfRange bool
}{
{f0, -205, -105, 0, 0, true},
{f0, -105, 80, 0, 180, false},
{f0, 5, 20, 105, 120, false},
{f0, 20, 1005, 120, 1000, false},
{f0, 1005, 2000, 0, 0, true},
{f1, -105, -5, 0, 0, true},
{f1, -5, 20, 0, 20, false},
{f1, 5, 20, 5, 20, false},
{f1, 20, 1005, 20, 1000, false},
{f1, 1005, 2000, 0, 0, true},
{f2, 5, 95, 0, 0, true},
{f2, 95, 120, 0, 20, false},
{f2, 105, 120, 5, 20, false},
{f2, 120, 1105, 20, 1000, false},
{f2, 1105, 2000, 0, 0, true},
} {
min, max, oor := tt.f.BaseValueBetween(tt.predMin, tt.predMax)
if oor != tt.expOutOfRange {
t.Fatalf("baseValueBetween calculation on %s, expected outOfRange %v, got %v", tt.f.Name, tt.expOutOfRange, oor)
} else if !reflect.DeepEqual(min, tt.expBaseValueMin) || !reflect.DeepEqual(max, tt.expBaseValueMax) {
t.Fatalf("baseValueBetween calculation on %s, expected min/max %v/%v, got %v/%v", tt.f.Name, tt.expBaseValueMin, tt.expBaseValueMax, min, max)
}
}
})
}

View file

@ -17,7 +17,6 @@ package pilosa_test
import (
"bytes"
"context"
"encoding/json"
"errors"
"fmt"
"io"
@ -817,245 +816,6 @@ func TestHandler_Frame_AttrStore_Diff(t *testing.T) {
}
}
// Ensure the handler can create a new field on an existing frame.
func TestHandler_Frame_AddField(t *testing.T) {
hldr := test.MustOpenHolder()
defer hldr.Close()
s := test.NewServer()
s.Handler.API.Holder = hldr.Holder
defer s.Close()
t.Run("OK", func(t *testing.T) {
idx := hldr.MustCreateIndexIfNotExists("i", pilosa.IndexOptions{})
f, err := idx.CreateFrameIfNotExists("f", pilosa.FrameOptions{})
if err != nil {
t.Fatal(err)
}
resp, err := http.Post(
s.URL+"/index/i/frame/f/field/x",
"application/json",
strings.NewReader(`{"type":"int","min":100,"max":200}`),
)
if err != nil {
t.Fatal(err)
} else if err := resp.Body.Close(); err != nil {
t.Fatal(err)
} else if resp.StatusCode != http.StatusOK {
t.Fatalf("unexpected status code: %d", resp.StatusCode)
}
if field := f.Field("x"); !reflect.DeepEqual(field, &pilosa.Field{Name: "x", Type: "int", Min: 100, Max: 200}) {
t.Fatalf("unexpected field: %#v", field)
}
})
t.Run("ErrInvalidFieldType", func(t *testing.T) {
idx := hldr.MustCreateIndexIfNotExists("i", pilosa.IndexOptions{})
if _, err := idx.CreateFrameIfNotExists("f", pilosa.FrameOptions{}); err != nil {
t.Fatal(err)
}
resp, err := http.Post(
s.URL+"/index/i/frame/f/field/x",
"application/json",
strings.NewReader(`{"type":"bad_type","min":100,"max":200}`),
)
if err != nil {
t.Fatal(err)
} else if body := MustReadAll(resp.Body); string(body) != `creating field: validating field: invalid field type`+"\n" {
t.Fatalf("unexpected body: %q", body)
} else if err := resp.Body.Close(); err != nil {
t.Fatal(err)
} else if resp.StatusCode != http.StatusInternalServerError {
t.Fatalf("unexpected status code: %d", resp.StatusCode)
}
})
t.Run("ErrInvalidFieldRange", func(t *testing.T) {
idx := hldr.MustCreateIndexIfNotExists("i", pilosa.IndexOptions{})
if _, err := idx.CreateFrameIfNotExists("f", pilosa.FrameOptions{}); err != nil {
t.Fatal(err)
}
resp, err := http.Post(
s.URL+"/index/i/frame/f/field/x",
"application/json",
strings.NewReader(`{"type":"int","min":200,"max":100}`),
)
if err != nil {
t.Fatal(err)
} else if body := MustReadAll(resp.Body); string(body) != `creating field: validating field: invalid field range`+"\n" {
t.Fatalf("unexpected body: %q", body)
} else if err := resp.Body.Close(); err != nil {
t.Fatal(err)
} else if resp.StatusCode != http.StatusInternalServerError {
t.Fatalf("unexpected status code: %d", resp.StatusCode)
}
})
t.Run("ErrFieldAlreadyExists", func(t *testing.T) {
idx := hldr.MustCreateIndexIfNotExists("i", pilosa.IndexOptions{})
if _, err := idx.CreateFrameIfNotExists("f", pilosa.FrameOptions{
Fields: []*pilosa.Field{{Name: "x", Type: pilosa.FieldTypeInt, Min: 0, Max: 100}},
}); err != nil {
t.Fatal(err)
}
resp, err := http.Post(
s.URL+"/index/i/frame/f/field/x",
"application/json",
strings.NewReader(`{"type":"int","min":0,"max":100}`),
)
if err != nil {
t.Fatal(err)
} else if body := MustReadAll(resp.Body); string(body) != `creating field: field already exists`+"\n" {
t.Fatalf("unexpected body: %q", body)
} else if err := resp.Body.Close(); err != nil {
t.Fatal(err)
} else if resp.StatusCode != http.StatusInternalServerError {
t.Fatalf("unexpected status code: %d", resp.StatusCode)
}
})
}
// Ensure the handler can delete existing fields.
func TestHandler_Frame_DeleteField(t *testing.T) {
hldr := test.MustOpenHolder()
defer hldr.Close()
s := test.NewServer()
s.Handler.API.Holder = hldr.Holder
defer s.Close()
t.Run("OK", func(t *testing.T) {
idx := hldr.MustCreateIndexIfNotExists("i", pilosa.IndexOptions{})
f, err := idx.CreateFrameIfNotExists("f", pilosa.FrameOptions{})
if err != nil {
t.Fatal(err)
} else if err := f.CreateField(&pilosa.Field{Name: "x", Type: pilosa.FieldTypeInt, Min: 0, Max: 100}); err != nil {
t.Fatal(err)
}
req, err := http.NewRequest("DELETE", s.URL+"/index/i/frame/f/field/x", nil)
if err != nil {
t.Fatal(err)
}
resp, err := http.DefaultClient.Do(req)
if err != nil {
t.Fatal(err)
} else if err := resp.Body.Close(); err != nil {
t.Fatal(err)
} else if resp.StatusCode != http.StatusOK {
t.Fatalf("unexpected status code: %d", resp.StatusCode)
}
if field := f.Field("x"); field != nil {
t.Fatalf("expected nil field, got: %#v", field)
}
})
t.Run("ErrFieldNotFound", func(t *testing.T) {
idx := hldr.MustCreateIndexIfNotExists("i", pilosa.IndexOptions{})
f, err := idx.CreateFrameIfNotExists("f", pilosa.FrameOptions{})
if err != nil {
t.Fatal(err)
} else if err := f.CreateField(&pilosa.Field{Name: "x", Type: pilosa.FieldTypeInt, Min: 0, Max: 100}); err != nil {
t.Fatal(err)
}
req, err := http.NewRequest("DELETE", s.URL+"/index/i/frame/f/field/y", nil)
if err != nil {
t.Fatal(err)
}
resp, err := http.DefaultClient.Do(req)
if err != nil {
t.Fatal(err)
} else if body, err := ioutil.ReadAll(resp.Body); err != nil {
t.Fatal(err)
} else if strings.TrimSpace(string(body)) != `deleting field: field not found` {
t.Fatalf("unexpected body: %q", body)
} else if err := resp.Body.Close(); err != nil {
t.Fatal(err)
} else if resp.StatusCode != http.StatusInternalServerError {
t.Fatalf("unexpected status code: %d", resp.StatusCode)
}
})
}
func TestHandler_Frame_GetFields(t *testing.T) {
hldr := test.MustOpenHolder()
defer hldr.Close()
s := test.NewServer()
s.Handler.API.Holder = hldr.Holder
defer s.Close()
t.Run("OK", func(t *testing.T) {
idx := hldr.MustCreateIndexIfNotExists("i", pilosa.IndexOptions{})
f, err := idx.CreateFrameIfNotExists("f", pilosa.FrameOptions{})
if err != nil {
t.Fatal(err)
} else if err := f.CreateField(&pilosa.Field{Name: "x", Type: pilosa.FieldTypeInt, Min: 1, Max: 100}); err != nil {
t.Fatal(err)
}
resp, err := http.Get(s.URL + "/index/i/frame/f/fields")
if err != nil {
t.Fatal(err)
} else if resp.StatusCode != http.StatusOK {
t.Fatalf("unexpected status code: %d", resp.StatusCode)
}
var fields FrameFields
body, err := ioutil.ReadAll(resp.Body)
if err != nil {
t.Fatal(err)
}
if err = json.Unmarshal([]byte(body), &fields); err != nil {
t.Fatal(err)
}
field := fields.Fields[0]
if field.Name != "x" {
t.Fatalf("expected field's name: x, actuall name: %v", field.Name)
} else if field.Min != 1 {
t.Fatalf("expected field's min: x, actuall min: %v", field.Min)
} else if field.Max != 100 {
t.Fatalf("expected field's max: x, actuall max: %v", field.Max)
}
})
t.Run("ErrFrameFieldNotAllowed", func(t *testing.T) {
idx := hldr.MustCreateIndexIfNotExists("i", pilosa.IndexOptions{})
_, err := idx.CreateFrameIfNotExists("f1", pilosa.FrameOptions{})
if err != nil {
t.Fatalf("creating frame: %v", err)
}
resp, err := http.Get(s.URL + "/index/i/frame/f1/fields")
if err != nil {
t.Fatal(err)
}
if err != nil {
t.Fatal(err)
} else if resp.StatusCode != http.StatusOK {
t.Fatalf("unexpected status code: %d", resp.StatusCode)
} else if body, err := ioutil.ReadAll(resp.Body); err != nil {
t.Fatal(err)
} else if strings.TrimSpace(string(body)) == `frame fields not allowed` {
t.Fatalf("shouldn't get frame fields not allowed error: %q", body)
}
})
}
type FrameFields struct {
Fields []pilosa.Field
}
// Ensure the handler can retrieve the version.
func TestHandler_Version(t *testing.T) {
hldr := test.MustOpenHolder()

View file

@ -57,7 +57,10 @@ func TestIndex_CreateFrame(t *testing.T) {
defer index.Close()
// Create frame with explicit quantum.
f, err := index.CreateFrame("f", pilosa.FrameOptions{TimeQuantum: pilosa.TimeQuantum("YMDH")})
f, err := index.CreateFrame("f", pilosa.FrameOptions{
Type: pilosa.FrameTypeTime,
TimeQuantum: pilosa.TimeQuantum("YMDH"),
})
if err != nil {
t.Fatal(err)
} else if q := f.TimeQuantum(); q != pilosa.TimeQuantum("YMDH") {
@ -74,103 +77,100 @@ func TestIndex_CreateFrame(t *testing.T) {
// Create frame with schema and verify it exists.
if f, err := index.CreateFrame("f", pilosa.FrameOptions{
Fields: []*pilosa.Field{
{Name: "field0", Type: pilosa.FieldTypeInt, Min: 10, Max: 20},
{Name: "field1", Type: pilosa.FieldTypeInt, Min: 11, Max: 21},
},
Type: pilosa.FrameTypeInt,
Min: 10,
Max: 20,
}); err != nil {
t.Fatal(err)
} else if !reflect.DeepEqual(f.Fields(), []*pilosa.Field{
{Name: "field0", Type: pilosa.FieldTypeInt, Min: 10, Max: 20},
{Name: "field1", Type: pilosa.FieldTypeInt, Min: 11, Max: 21},
}) {
t.Fatalf("unexpected fields: %#v", f.Fields())
} else if !reflect.DeepEqual(f.Type(), pilosa.FrameTypeInt) {
t.Fatalf("unexpected type: %#v", f.Type())
}
// Reopen the index & verify the fields are loaded.
if err := index.Reopen(); err != nil {
t.Fatal(err)
} else if f := index.Frame("f"); !reflect.DeepEqual(f.Fields(), []*pilosa.Field{
{Name: "field0", Type: pilosa.FieldTypeInt, Min: 10, Max: 20},
{Name: "field1", Type: pilosa.FieldTypeInt, Min: 11, Max: 21},
}) {
t.Fatalf("unexpected fields after reopen: %#v", f.Fields())
} else if f := index.Frame("f"); !reflect.DeepEqual(f.Type(), pilosa.FrameTypeInt) {
t.Fatalf("unexpected type after reopen: %#v", f.Type())
}
})
t.Run("ErrRangeCacheAllowed", func(t *testing.T) {
index := test.MustOpenIndex()
defer index.Close()
// TODO: These errors don't apply here. Instead, we need these tests
// on frame creation FrameOptions validation.
/*
t.Run("ErrRangeCacheAllowed", func(t *testing.T) {
index := test.MustOpenIndex()
defer index.Close()
if _, err := index.CreateFrame("f", pilosa.FrameOptions{
CacheType: pilosa.CacheTypeRanked,
}); err != nil {
t.Fatal(err)
}
})
if _, err := index.CreateFrame("f", pilosa.FrameOptions{
CacheType: pilosa.CacheTypeRanked,
}); err != nil {
t.Fatal(err)
}
})
t.Run("BSIFieldsWithCacheTypeNone", func(t *testing.T) {
index := test.MustOpenIndex()
defer index.Close()
if _, err := index.CreateFrame("f", pilosa.FrameOptions{
CacheType: pilosa.CacheTypeNone,
CacheSize: uint32(5),
}); err != nil {
t.Fatal(err)
}
})
t.Run("BSIFieldsWithCacheTypeNone", func(t *testing.T) {
index := test.MustOpenIndex()
defer index.Close()
if _, err := index.CreateFrame("f", pilosa.FrameOptions{
CacheType: pilosa.CacheTypeNone,
CacheSize: uint32(5),
}); err != nil {
t.Fatal(err)
}
})
t.Run("ErrFrameFieldsAllowed", func(t *testing.T) {
index := test.MustOpenIndex()
defer index.Close()
t.Run("ErrFrameFieldsAllowed", func(t *testing.T) {
index := test.MustOpenIndex()
defer index.Close()
if _, err := index.CreateFrame("f", pilosa.FrameOptions{
Fields: []*pilosa.Field{
{Name: "field0", Type: pilosa.FieldTypeInt},
},
}); err != nil {
t.Fatal(err)
}
})
if _, err := index.CreateFrame("f", pilosa.FrameOptions{
Fields: []*pilosa.Field{
{Name: "field0", Type: pilosa.FieldTypeInt},
},
}); err != nil {
t.Fatal(err)
}
})
t.Run("ErrFieldNameRequired", func(t *testing.T) {
index := test.MustOpenIndex()
defer index.Close()
t.Run("ErrFieldNameRequired", func(t *testing.T) {
index := test.MustOpenIndex()
defer index.Close()
if _, err := index.CreateFrame("f", pilosa.FrameOptions{
Fields: []*pilosa.Field{
{Name: "", Type: pilosa.FieldTypeInt},
},
}); err != pilosa.ErrFieldNameRequired {
t.Fatal(err)
}
})
if _, err := index.CreateFrame("f", pilosa.FrameOptions{
Fields: []*pilosa.Field{
{Name: "", Type: pilosa.FieldTypeInt},
},
}); err != pilosa.ErrFieldNameRequired {
t.Fatal(err)
}
})
t.Run("ErrInvalidFieldType", func(t *testing.T) {
index := test.MustOpenIndex()
defer index.Close()
t.Run("ErrInvalidFieldType", func(t *testing.T) {
index := test.MustOpenIndex()
defer index.Close()
if _, err := index.CreateFrame("f", pilosa.FrameOptions{
Fields: []*pilosa.Field{
{Name: "field0", Type: "bad_type"},
},
}); err != pilosa.ErrInvalidFieldType {
t.Fatal(err)
}
})
if _, err := index.CreateFrame("f", pilosa.FrameOptions{
Fields: []*pilosa.Field{
{Name: "field0", Type: "bad_type"},
},
}); err != pilosa.ErrInvalidFieldType {
t.Fatal(err)
}
})
t.Run("ErrInvalidFieldRange", func(t *testing.T) {
index := test.MustOpenIndex()
defer index.Close()
t.Run("ErrInvalidFieldRange", func(t *testing.T) {
index := test.MustOpenIndex()
defer index.Close()
if _, err := index.CreateFrame("f", pilosa.FrameOptions{
Fields: []*pilosa.Field{
{Name: "field0", Type: pilosa.FieldTypeInt, Min: 100, Max: 50},
},
}); err != pilosa.ErrInvalidFieldRange {
t.Fatal(err)
}
})
if _, err := index.CreateFrame("f", pilosa.FrameOptions{
Fields: []*pilosa.Field{
{Name: "field0", Type: pilosa.FieldTypeInt, Min: 100, Max: 50},
},
}); err != pilosa.ErrInvalidFieldRange {
t.Fatal(err)
}
})
*/
})
}

View file

@ -29,12 +29,12 @@ type Frame struct {
}
// NewFrame returns a new instance of Frame d/0.
func NewFrame() *Frame {
func NewFrame(opt ...pilosa.FrameOption) *Frame {
path, err := ioutil.TempDir("", "pilosa-frame-")
if err != nil {
panic(err)
}
frame, err := pilosa.NewFrame(path, "i", "f")
frame, err := pilosa.NewFrame(path, "i", "f", opt...)
if err != nil {
panic(err)
}
@ -42,8 +42,8 @@ func NewFrame() *Frame {
}
// MustOpenFrame returns a new, opened frame at a temporary path. Panic on error.
func MustOpenFrame() *Frame {
f := NewFrame()
func MustOpenFrame(opt ...pilosa.FrameOption) *Frame {
f := NewFrame(opt...)
if err := f.Open(); err != nil {
panic(err)
}