blob: 731b689a6fdf9544e410feedd73cd8212bf4237a [file] [log] [blame]
Adam Sadovskyaba9d502015-04-10 22:06:06 -07001// Copyright 2015 The Vanadium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style
3// license that can be found in the LICENSE file.
4
Adam Sadovskyaba9d502015-04-10 22:06:06 -07005package nosql_test
6
Adam Sadovskyaba9d502015-04-10 22:06:06 -07007import (
Adam Sadovsky13922e32015-05-19 17:39:59 -07008 "reflect"
Adam Sadovskyaba9d502015-04-10 22:06:06 -07009 "testing"
10
Adam Sadovskyaba9d502015-04-10 22:06:06 -070011 "v.io/syncbase/v23/syncbase"
Adam Sadovsky13922e32015-05-19 17:39:59 -070012 "v.io/syncbase/v23/syncbase/nosql"
John Kline4894fb12015-06-17 09:06:56 -070013 "v.io/syncbase/v23/syncbase/nosql/syncql"
Adam Sadovskyfa5f16f2015-05-04 15:33:22 -070014 tu "v.io/syncbase/v23/syncbase/testutil"
Adam Sadovskyfd0cd952015-06-04 22:23:51 -070015 "v.io/v23/naming"
John Kline4894fb12015-06-17 09:06:56 -070016 "v.io/v23/vdl"
Adam Sadovsky13922e32015-05-19 17:39:59 -070017 "v.io/v23/verror"
Adam Sadovsky67e5f7c2015-05-11 16:04:15 -070018 _ "v.io/x/ref/runtime/factories/generic"
Adam Sadovskyaba9d502015-04-10 22:06:06 -070019)
20
Adam Sadovskyaba9d502015-04-10 22:06:06 -070021// TODO(sadovsky): Finish writing tests.
Sergey Rogulenko445e0412015-06-18 23:06:11 -070022// TODO(rogulenko): Test perms checking for Glob and Exec.
Adam Sadovskyaba9d502015-04-10 22:06:06 -070023
Adam Sadovskyfd0cd952015-06-04 22:23:51 -070024// Tests various Name, FullName, and Key methods.
Adam Sadovskyaba9d502015-04-10 22:06:06 -070025func TestNameAndKey(t *testing.T) {
Adam Sadovskyfd0cd952015-06-04 22:23:51 -070026 d := syncbase.NewService("s").App("a").NoSQLDatabase("d")
Adam Sadovskyaba9d502015-04-10 22:06:06 -070027 tb := d.Table("tb")
28 r := tb.Row("r")
29
30 if d.Name() != "d" {
Adam Sadovsky13922e32015-05-19 17:39:59 -070031 t.Errorf("Wrong name: %q", d.Name())
Adam Sadovskyaba9d502015-04-10 22:06:06 -070032 }
Adam Sadovskyfd0cd952015-06-04 22:23:51 -070033 if d.FullName() != naming.Join("s", "a", "d") {
34 t.Errorf("Wrong full name: %q", d.FullName())
35 }
Adam Sadovskyaba9d502015-04-10 22:06:06 -070036 if tb.Name() != "tb" {
Adam Sadovsky13922e32015-05-19 17:39:59 -070037 t.Errorf("Wrong name: %q", tb.Name())
Adam Sadovskyaba9d502015-04-10 22:06:06 -070038 }
Adam Sadovskyfd0cd952015-06-04 22:23:51 -070039 if tb.FullName() != naming.Join("s", "a", "d", "tb") {
40 t.Errorf("Wrong full name: %q", tb.FullName())
41 }
Adam Sadovskyaba9d502015-04-10 22:06:06 -070042 if r.Key() != "r" {
Adam Sadovsky13922e32015-05-19 17:39:59 -070043 t.Errorf("Wrong key: %q", r.Key())
Adam Sadovskyaba9d502015-04-10 22:06:06 -070044 }
Adam Sadovskyfd0cd952015-06-04 22:23:51 -070045 if r.FullName() != naming.Join("s", "a", "d", "tb", "r") {
46 t.Errorf("Wrong full name: %q", r.FullName())
47 }
Adam Sadovskyaba9d502015-04-10 22:06:06 -070048}
49
Adam Sadovskyfa5f16f2015-05-04 15:33:22 -070050// Tests that Database.Create works as expected.
51func TestDatabaseCreate(t *testing.T) {
52 ctx, sName, cleanup := tu.SetupOrDie(nil)
Adam Sadovskyaba9d502015-04-10 22:06:06 -070053 defer cleanup()
Adam Sadovsky13922e32015-05-19 17:39:59 -070054 a := tu.CreateApp(t, ctx, syncbase.NewService(sName), "a")
Adam Sadovskyfa5f16f2015-05-04 15:33:22 -070055 tu.TestCreate(t, ctx, a)
Adam Sadovskyaba9d502015-04-10 22:06:06 -070056}
57
John Kline4894fb12015-06-17 09:06:56 -070058// Tests that Database.Exec works as expected.
59// Note: More comprehensive client/server tests are in the exec_test
60// directory. Also, exec is tested in its entirety in
61// v23/syncbase/nosql/internal/query/...
62func TestExec(t *testing.T) {
63 ctx, sName, cleanup := tu.SetupOrDie(nil)
64 defer cleanup()
65 a := tu.CreateApp(t, ctx, syncbase.NewService(sName), "a")
66 d := tu.CreateNoSQLDatabase(t, ctx, a, "d")
67 tb := tu.CreateTable(t, ctx, d, "tb")
68
69 foo := Foo{I: 4, S: "f"}
70 if err := tb.Put(ctx, "foo", foo); err != nil {
71 t.Fatalf("tb.Put() failed: %v", err)
72 }
73
74 bar := Bar{F: 0.5, S: "b"}
75 // NOTE: not best practice, but store bar as
76 // optional (by passing the address of bar to Put).
77 // This tests auto-dereferencing.
78 if err := tb.Put(ctx, "bar", &bar); err != nil {
79 t.Fatalf("tb.Put() failed: %v", err)
80 }
81
82 baz := Baz{Name: "John Doe", Active: true}
83 if err := tb.Put(ctx, "baz", baz); err != nil {
84 t.Fatalf("tb.Put() failed: %v", err)
85 }
86
87 tu.CheckExec(t, ctx, d, "select k, v.Name from tb where t = \"Baz\"",
88 []string{"k", "v.Name"},
89 [][]*vdl.Value{
90 []*vdl.Value{vdl.ValueOf("baz"), vdl.ValueOf(baz.Name)},
91 })
92
93 tu.CheckExec(t, ctx, d, "select k, v from tb",
94 []string{"k", "v"},
95 [][]*vdl.Value{
96 []*vdl.Value{vdl.ValueOf("bar"), vdl.ValueOf(bar)},
97 []*vdl.Value{vdl.ValueOf("baz"), vdl.ValueOf(baz)},
98 []*vdl.Value{vdl.ValueOf("foo"), vdl.ValueOf(foo)},
99 })
100
101 tu.CheckExec(t, ctx, d, "select k, v from tb where k like \"ba%\"",
102 []string{"k", "v"},
103 [][]*vdl.Value{
104 []*vdl.Value{vdl.ValueOf("bar"), vdl.ValueOf(bar)},
105 []*vdl.Value{vdl.ValueOf("baz"), vdl.ValueOf(baz)},
106 })
107
108 tu.CheckExec(t, ctx, d, "select k, v from tb where v.Active = true",
109 []string{"k", "v"},
110 [][]*vdl.Value{
111 []*vdl.Value{vdl.ValueOf("baz"), vdl.ValueOf(baz)},
112 })
113
114 tu.CheckExec(t, ctx, d, "select k, v from tb where t = \"Bar\"",
115 []string{"k", "v"},
116 [][]*vdl.Value{
117 []*vdl.Value{vdl.ValueOf("bar"), vdl.ValueOf(bar)},
118 })
119
120 tu.CheckExec(t, ctx, d, "select k, v from tb where v.F = 0.5",
121 []string{"k", "v"},
122 [][]*vdl.Value{
123 []*vdl.Value{vdl.ValueOf("bar"), vdl.ValueOf(bar)},
124 })
125
126 tu.CheckExec(t, ctx, d, "select k, v from tb where t = \"Baz\"",
127 []string{"k", "v"},
128 [][]*vdl.Value{
129 []*vdl.Value{vdl.ValueOf("baz"), vdl.ValueOf(baz)},
130 })
131
132 tu.CheckExecError(t, ctx, d, "select k, v from foo", syncql.ErrTableCantAccess.ID)
133}
134
Adam Sadovskyaba9d502015-04-10 22:06:06 -0700135// Tests that Database.Delete works as expected.
Adam Sadovskyfa5f16f2015-05-04 15:33:22 -0700136func TestDatabaseDelete(t *testing.T) {
137 ctx, sName, cleanup := tu.SetupOrDie(nil)
138 defer cleanup()
Adam Sadovsky13922e32015-05-19 17:39:59 -0700139 a := tu.CreateApp(t, ctx, syncbase.NewService(sName), "a")
Adam Sadovskyfa5f16f2015-05-04 15:33:22 -0700140 tu.TestDelete(t, ctx, a)
Adam Sadovskyaba9d502015-04-10 22:06:06 -0700141}
142
Adam Sadovsky13922e32015-05-19 17:39:59 -0700143// Tests that Database.ListTables works as expected.
144func TestListTables(t *testing.T) {
145 ctx, sName, cleanup := tu.SetupOrDie(nil)
146 defer cleanup()
147 a := tu.CreateApp(t, ctx, syncbase.NewService(sName), "a")
148 d := tu.CreateNoSQLDatabase(t, ctx, a, "d")
149 tu.TestListChildren(t, ctx, d)
150}
151
Adam Sadovskyfa5f16f2015-05-04 15:33:22 -0700152// Tests that Database.{Set,Get}Permissions work as expected.
153func TestDatabasePerms(t *testing.T) {
154 ctx, sName, cleanup := tu.SetupOrDie(nil)
155 defer cleanup()
Adam Sadovsky13922e32015-05-19 17:39:59 -0700156 a := tu.CreateApp(t, ctx, syncbase.NewService(sName), "a")
157 d := tu.CreateNoSQLDatabase(t, ctx, a, "d")
Adam Sadovskyfa5f16f2015-05-04 15:33:22 -0700158 tu.TestPerms(t, ctx, d)
Adam Sadovskyaba9d502015-04-10 22:06:06 -0700159}
160
Adam Sadovskyfa5f16f2015-05-04 15:33:22 -0700161// Tests that Database.CreateTable works as expected.
162func TestTableCreate(t *testing.T) {
Adam Sadovsky13922e32015-05-19 17:39:59 -0700163 ctx, sName, cleanup := tu.SetupOrDie(nil)
164 defer cleanup()
165 a := tu.CreateApp(t, ctx, syncbase.NewService(sName), "a")
166 d := tu.CreateNoSQLDatabase(t, ctx, a, "d")
167 tu.TestCreate(t, ctx, d)
Adam Sadovskyfa5f16f2015-05-04 15:33:22 -0700168}
169
170// Tests that Database.DeleteTable works as expected.
171func TestTableDelete(t *testing.T) {
Adam Sadovsky13922e32015-05-19 17:39:59 -0700172 ctx, sName, cleanup := tu.SetupOrDie(nil)
173 defer cleanup()
174 a := tu.CreateApp(t, ctx, syncbase.NewService(sName), "a")
175 d := tu.CreateNoSQLDatabase(t, ctx, a, "d")
176 tu.TestDelete(t, ctx, d)
Adam Sadovskyfa5f16f2015-05-04 15:33:22 -0700177}
178
179// Tests that Table.{Set,Get,Delete}Permissions methods work as expected.
180func TestTablePerms(t *testing.T) {
Adam Sadovskyda069202015-06-24 12:56:11 -0700181 ctx, clientACtx, sName, rootp, cleanup := tu.SetupOrDieCustom("clientA", "server", nil)
Sergey Rogulenko445e0412015-06-18 23:06:11 -0700182 defer cleanup()
Adam Sadovskyda069202015-06-24 12:56:11 -0700183 clientBCtx := tu.NewCtx(ctx, rootp, "clientB")
Sergey Rogulenko445e0412015-06-18 23:06:11 -0700184 a := tu.CreateApp(t, clientACtx, syncbase.NewService(sName), "a")
185 d := tu.CreateNoSQLDatabase(t, clientACtx, a, "d")
186 tb := tu.CreateTable(t, clientACtx, d, "tb")
187
188 // Permission objects.
Adam Sadovskyda069202015-06-24 12:56:11 -0700189 aAndB := tu.DefaultPerms("root/clientA", "root/clientB")
190 aOnly := tu.DefaultPerms("root/clientA")
191 bOnly := tu.DefaultPerms("root/clientB")
Sergey Rogulenko445e0412015-06-18 23:06:11 -0700192
193 // Set initial permissions.
194 if err := tb.SetPermissions(clientACtx, nosql.Prefix(""), aAndB); err != nil {
195 t.Fatalf("tb.SetPermissions() failed: %v", err)
196 }
197 if err := tb.SetPermissions(clientACtx, nosql.Prefix("prefix"), aAndB); err != nil {
198 t.Fatalf("tb.SetPermissions() failed: %v", err)
199 }
200 if err := tb.SetPermissions(clientBCtx, nosql.Prefix("prefix"), aAndB); err != nil {
201 t.Fatalf("tb.SetPermissions() failed: %v", err)
202 }
203 if err := tb.SetPermissions(clientACtx, nosql.Prefix("prefix_a"), aOnly); err != nil {
204 t.Fatalf("tb.SetPermissions() failed: %v", err)
205 }
206 if err := tb.SetPermissions(clientBCtx, nosql.Prefix("prefix_b"), bOnly); err != nil {
207 t.Fatalf("tb.SetPermissions() failed: %v", err)
208 }
209
210 // Checks A has no access to 'prefix_b' and vice versa.
211 if err := tb.SetPermissions(clientACtx, nosql.Prefix("prefix_b"), aOnly); verror.ErrorID(err) != verror.ErrNoAccess.ID {
212 t.Fatalf("tb.SetPermissions() should have failed: %v", err)
213 }
214 if err := tb.SetPermissions(clientACtx, nosql.Prefix("prefix_b_suffix"), aOnly); verror.ErrorID(err) != verror.ErrNoAccess.ID {
215 t.Fatalf("tb.SetPermissions() should have failed: %v", err)
216 }
217 if err := tb.SetPermissions(clientBCtx, nosql.Prefix("prefix_a"), bOnly); verror.ErrorID(err) != verror.ErrNoAccess.ID {
218 t.Fatalf("tb.SetPermissions() should have failed: %v", err)
219 }
220 if err := tb.SetPermissions(clientBCtx, nosql.Prefix("prefix_a_suffix"), bOnly); verror.ErrorID(err) != verror.ErrNoAccess.ID {
221 t.Fatalf("tb.SetPermissions() should have failed: %v", err)
222 }
223
224 // Check GetPermissions.
225 wantPerms := []nosql.PrefixPermissions{
226 nosql.PrefixPermissions{Prefix: nosql.Prefix(""), Perms: aAndB},
227 }
228 if got, _ := tb.GetPermissions(clientACtx, ""); !reflect.DeepEqual(got, wantPerms) {
229 t.Fatalf("Unexpected permissions: got %v, want %v", got, wantPerms)
230 }
231 if got, _ := tb.GetPermissions(clientACtx, "abc"); !reflect.DeepEqual(got, wantPerms) {
232 t.Fatalf("Unexpected permissions: got %v, want %v", got, wantPerms)
233 }
234 wantPerms = []nosql.PrefixPermissions{
235 nosql.PrefixPermissions{Prefix: nosql.Prefix("prefix"), Perms: aAndB},
236 nosql.PrefixPermissions{Prefix: nosql.Prefix(""), Perms: aAndB},
237 }
238 if got, _ := tb.GetPermissions(clientACtx, "prefix"); !reflect.DeepEqual(got, wantPerms) {
239 t.Fatalf("Unexpected permissions: got %v, want %v", got, wantPerms)
240 }
241 if got, _ := tb.GetPermissions(clientACtx, "prefix_c"); !reflect.DeepEqual(got, wantPerms) {
242 t.Fatalf("Unexpected permissions: got %v, want %v", got, wantPerms)
243 }
244 wantPerms = []nosql.PrefixPermissions{
245 nosql.PrefixPermissions{Prefix: nosql.Prefix("prefix_a"), Perms: aOnly},
246 nosql.PrefixPermissions{Prefix: nosql.Prefix("prefix"), Perms: aAndB},
247 nosql.PrefixPermissions{Prefix: nosql.Prefix(""), Perms: aAndB},
248 }
249 if got, _ := tb.GetPermissions(clientACtx, "prefix_a"); !reflect.DeepEqual(got, wantPerms) {
250 t.Fatalf("Unexpected permissions: got %v, want %v", got, wantPerms)
251 }
252 if got, _ := tb.GetPermissions(clientACtx, "prefix_a_suffix"); !reflect.DeepEqual(got, wantPerms) {
253 t.Fatalf("Unexpected permissions: got %v, want %v", got, wantPerms)
254 }
255 wantPerms = []nosql.PrefixPermissions{
256 nosql.PrefixPermissions{Prefix: nosql.Prefix("prefix_b"), Perms: bOnly},
257 nosql.PrefixPermissions{Prefix: nosql.Prefix("prefix"), Perms: aAndB},
258 nosql.PrefixPermissions{Prefix: nosql.Prefix(""), Perms: aAndB},
259 }
260 if got, _ := tb.GetPermissions(clientACtx, "prefix_b"); !reflect.DeepEqual(got, wantPerms) {
261 t.Fatalf("Unexpected permissions: got %v, want %v", got, wantPerms)
262 }
263 if got, _ := tb.GetPermissions(clientACtx, "prefix_b_suffix"); !reflect.DeepEqual(got, wantPerms) {
264 t.Fatalf("Unexpected permissions: got %v, want %v", got, wantPerms)
265 }
266
267 // Delete some prefix permissions and check again.
268 // Check that A can't delete permissions of B.
269 if err := tb.DeletePermissions(clientACtx, nosql.Prefix("prefix_b")); verror.ErrorID(err) != verror.ErrNoAccess.ID {
270 t.Fatalf("tb.DeletePermissions() should have failed: %v", err)
271 }
272 if err := tb.DeletePermissions(clientBCtx, nosql.Prefix("prefix_a")); verror.ErrorID(err) != verror.ErrNoAccess.ID {
273 t.Fatalf("tb.DeletePermissions() should have failed: %v", err)
274 }
275 // Delete 'prefix' and 'prefix_a'
276 if err := tb.DeletePermissions(clientACtx, nosql.Prefix("prefix")); err != nil {
277 t.Fatalf("tb.DeletePermissions() failed: %v", err)
278 }
279 if err := tb.DeletePermissions(clientACtx, nosql.Prefix("prefix_a")); err != nil {
280 t.Fatalf("tb.DeletePermissions() failed: %v", err)
281 }
282 // Check DeletePermissions is idempotent.
283 if err := tb.DeletePermissions(clientACtx, nosql.Prefix("prefix")); err != nil {
284 t.Fatalf("tb.DeletePermissions() failed: %v", err)
285 }
286
287 // Check GetPermissions again.
288 wantPerms = []nosql.PrefixPermissions{
289 nosql.PrefixPermissions{Prefix: nosql.Prefix(""), Perms: aAndB},
290 }
291 if got, _ := tb.GetPermissions(clientACtx, ""); !reflect.DeepEqual(got, wantPerms) {
292 t.Fatalf("Unexpected permissions: got %v, want %v", got, wantPerms)
293 }
294 if got, _ := tb.GetPermissions(clientACtx, "prefix"); !reflect.DeepEqual(got, wantPerms) {
295 t.Fatalf("Unexpected permissions: got %v, want %v", got, wantPerms)
296 }
297 if got, _ := tb.GetPermissions(clientACtx, "prefix_a"); !reflect.DeepEqual(got, wantPerms) {
298 t.Fatalf("Unexpected permissions: got %v, want %v", got, wantPerms)
299 }
300 if got, _ := tb.GetPermissions(clientACtx, "prefix_a_suffix"); !reflect.DeepEqual(got, wantPerms) {
301 t.Fatalf("Unexpected permissions: got %v, want %v", got, wantPerms)
302 }
303 wantPerms = []nosql.PrefixPermissions{
304 nosql.PrefixPermissions{Prefix: nosql.Prefix("prefix_b"), Perms: bOnly},
305 nosql.PrefixPermissions{Prefix: nosql.Prefix(""), Perms: aAndB},
306 }
307 if got, _ := tb.GetPermissions(clientACtx, "prefix_b"); !reflect.DeepEqual(got, wantPerms) {
308 t.Fatalf("Unexpected permissions: got %v, want %v", got, wantPerms)
309 }
310 if got, _ := tb.GetPermissions(clientACtx, "prefix_b_suffix"); !reflect.DeepEqual(got, wantPerms) {
311 t.Fatalf("Unexpected permissions: got %v, want %v", got, wantPerms)
312 }
313
314 // Remove B from table-level permissions and check B has no access.
315 if err := tb.SetPermissions(clientACtx, nosql.Prefix(""), aOnly); err != nil {
316 t.Fatalf("tb.SetPermissions() failed: %v", err)
317 }
318 if _, err := tb.GetPermissions(clientBCtx, ""); verror.ErrorID(err) != verror.ErrNoAccess.ID {
319 t.Fatalf("tb.GetPermissions() should have failed: %v", err)
320 }
321 if _, err := tb.GetPermissions(clientBCtx, "prefix_b"); verror.ErrorID(err) != verror.ErrNoAccess.ID {
322 t.Fatalf("tb.GetPermissions() should have failed: %v", err)
323 }
324 if err := tb.SetPermissions(clientBCtx, nosql.Prefix(""), bOnly); verror.ErrorID(err) != verror.ErrNoAccess.ID {
325 t.Fatalf("tb.SetPermissions() should have failed: %v", err)
326 }
327 if err := tb.SetPermissions(clientBCtx, nosql.Prefix("prefix_b"), bOnly); verror.ErrorID(err) != verror.ErrNoAccess.ID {
328 t.Fatalf("tb.SetPermissions() should have failed: %v", err)
329 }
Adam Sadovskyaba9d502015-04-10 22:06:06 -0700330}
331
Adam Sadovsky13922e32015-05-19 17:39:59 -0700332////////////////////////////////////////
333// Tests involving rows
334
335type Foo struct {
336 I int
337 S string
338}
339
340type Bar struct {
341 F float32
342 S string
343}
344
John Kline4894fb12015-06-17 09:06:56 -0700345type Baz struct {
346 Name string
347 Active bool
348}
349
Adam Sadovsky13922e32015-05-19 17:39:59 -0700350// Tests that Table.Scan works as expected.
351func TestTableScan(t *testing.T) {
352 ctx, sName, cleanup := tu.SetupOrDie(nil)
353 defer cleanup()
354 a := tu.CreateApp(t, ctx, syncbase.NewService(sName), "a")
355 d := tu.CreateNoSQLDatabase(t, ctx, a, "d")
356 tb := tu.CreateTable(t, ctx, d, "tb")
357
Adam Sadovskyfd0cd952015-06-04 22:23:51 -0700358 tu.CheckScan(t, ctx, tb, nosql.Prefix(""), []string{}, []interface{}{})
Adam Sadovsky13922e32015-05-19 17:39:59 -0700359
360 fooWant := Foo{I: 4, S: "f"}
361 if err := tb.Put(ctx, "foo", &fooWant); err != nil {
362 t.Fatalf("tb.Put() failed: %v", err)
363 }
364 barWant := Bar{F: 0.5, S: "b"}
365 if err := tb.Put(ctx, "bar", &barWant); err != nil {
366 t.Fatalf("tb.Put() failed: %v", err)
367 }
368
369 // Match all keys.
Adam Sadovskyfd0cd952015-06-04 22:23:51 -0700370 tu.CheckScan(t, ctx, tb, nosql.Prefix(""), []string{"bar", "foo"}, []interface{}{&barWant, &fooWant})
371 tu.CheckScan(t, ctx, tb, nosql.Range("", ""), []string{"bar", "foo"}, []interface{}{&barWant, &fooWant})
372 tu.CheckScan(t, ctx, tb, nosql.Range("", "z"), []string{"bar", "foo"}, []interface{}{&barWant, &fooWant})
373 tu.CheckScan(t, ctx, tb, nosql.Range("a", ""), []string{"bar", "foo"}, []interface{}{&barWant, &fooWant})
374 tu.CheckScan(t, ctx, tb, nosql.Range("a", "z"), []string{"bar", "foo"}, []interface{}{&barWant, &fooWant})
Adam Sadovsky13922e32015-05-19 17:39:59 -0700375
376 // Match "bar" only.
Adam Sadovskyfd0cd952015-06-04 22:23:51 -0700377 tu.CheckScan(t, ctx, tb, nosql.Prefix("b"), []string{"bar"}, []interface{}{&barWant})
378 tu.CheckScan(t, ctx, tb, nosql.Prefix("bar"), []string{"bar"}, []interface{}{&barWant})
379 tu.CheckScan(t, ctx, tb, nosql.Range("bar", "baz"), []string{"bar"}, []interface{}{&barWant})
380 tu.CheckScan(t, ctx, tb, nosql.Range("bar", "foo"), []string{"bar"}, []interface{}{&barWant})
381 tu.CheckScan(t, ctx, tb, nosql.Range("", "foo"), []string{"bar"}, []interface{}{&barWant})
Adam Sadovsky13922e32015-05-19 17:39:59 -0700382
383 // Match "foo" only.
Adam Sadovskyfd0cd952015-06-04 22:23:51 -0700384 tu.CheckScan(t, ctx, tb, nosql.Prefix("f"), []string{"foo"}, []interface{}{&fooWant})
385 tu.CheckScan(t, ctx, tb, nosql.Prefix("foo"), []string{"foo"}, []interface{}{&fooWant})
386 tu.CheckScan(t, ctx, tb, nosql.Range("foo", "fox"), []string{"foo"}, []interface{}{&fooWant})
387 tu.CheckScan(t, ctx, tb, nosql.Range("foo", ""), []string{"foo"}, []interface{}{&fooWant})
Adam Sadovsky13922e32015-05-19 17:39:59 -0700388
389 // Match nothing.
Adam Sadovskyfd0cd952015-06-04 22:23:51 -0700390 tu.CheckScan(t, ctx, tb, nosql.Range("a", "bar"), []string{}, []interface{}{})
391 tu.CheckScan(t, ctx, tb, nosql.Range("bar", "bar"), []string{}, []interface{}{})
392 tu.CheckScan(t, ctx, tb, nosql.Prefix("z"), []string{}, []interface{}{})
Adam Sadovsky13922e32015-05-19 17:39:59 -0700393}
394
Adam Sadovskyc5cc4a32015-06-02 18:44:46 -0700395// Tests that Table.Delete works as expected.
396func TestTableDeleteRowRange(t *testing.T) {
397 ctx, sName, cleanup := tu.SetupOrDie(nil)
398 defer cleanup()
399 a := tu.CreateApp(t, ctx, syncbase.NewService(sName), "a")
400 d := tu.CreateNoSQLDatabase(t, ctx, a, "d")
401 tb := tu.CreateTable(t, ctx, d, "tb")
402
Adam Sadovskyfd0cd952015-06-04 22:23:51 -0700403 tu.CheckScan(t, ctx, tb, nosql.Prefix(""), []string{}, []interface{}{})
Adam Sadovskyc5cc4a32015-06-02 18:44:46 -0700404
405 // Put foo and bar.
406 fooWant := Foo{I: 4, S: "f"}
407 if err := tb.Put(ctx, "foo", &fooWant); err != nil {
408 t.Fatalf("tb.Put() failed: %v", err)
409 }
410 barWant := Bar{F: 0.5, S: "b"}
411 if err := tb.Put(ctx, "bar", &barWant); err != nil {
412 t.Fatalf("tb.Put() failed: %v", err)
413 }
Adam Sadovskyfd0cd952015-06-04 22:23:51 -0700414 tu.CheckScan(t, ctx, tb, nosql.Prefix(""), []string{"bar", "foo"}, []interface{}{&barWant, &fooWant})
Adam Sadovskyc5cc4a32015-06-02 18:44:46 -0700415
416 // Delete foo.
417 if err := tb.Delete(ctx, nosql.Prefix("f")); err != nil {
418 t.Fatalf("tb.Delete() failed: %v", err)
419 }
Adam Sadovskyfd0cd952015-06-04 22:23:51 -0700420 tu.CheckScan(t, ctx, tb, nosql.Prefix(""), []string{"bar"}, []interface{}{&barWant})
Adam Sadovskyc5cc4a32015-06-02 18:44:46 -0700421
422 // Restore foo.
423 if err := tb.Put(ctx, "foo", &fooWant); err != nil {
424 t.Fatalf("tb.Put() failed: %v", err)
425 }
Adam Sadovskyfd0cd952015-06-04 22:23:51 -0700426 tu.CheckScan(t, ctx, tb, nosql.Prefix(""), []string{"bar", "foo"}, []interface{}{&barWant, &fooWant})
Adam Sadovskyc5cc4a32015-06-02 18:44:46 -0700427
428 // Delete everything.
429 if err := tb.Delete(ctx, nosql.Prefix("")); err != nil {
430 t.Fatalf("tb.Delete() failed: %v", err)
431 }
Adam Sadovskyfd0cd952015-06-04 22:23:51 -0700432 tu.CheckScan(t, ctx, tb, nosql.Prefix(""), []string{}, []interface{}{})
Adam Sadovskyc5cc4a32015-06-02 18:44:46 -0700433}
434
Adam Sadovskyaba9d502015-04-10 22:06:06 -0700435// Tests that Table.{Get,Put,Delete} work as expected.
436func TestTableRowMethods(t *testing.T) {
Adam Sadovsky13922e32015-05-19 17:39:59 -0700437 ctx, sName, cleanup := tu.SetupOrDie(nil)
438 defer cleanup()
439 a := tu.CreateApp(t, ctx, syncbase.NewService(sName), "a")
440 d := tu.CreateNoSQLDatabase(t, ctx, a, "d")
441 tb := tu.CreateTable(t, ctx, d, "tb")
442
443 got, want := Foo{}, Foo{I: 4, S: "foo"}
444 if err := tb.Get(ctx, "f", &got); verror.ErrorID(err) != verror.ErrNoExist.ID {
445 t.Fatalf("tb.Get() should have failed: %v", err)
446 }
447 if err := tb.Put(ctx, "f", &want); err != nil {
448 t.Fatalf("tb.Put() failed: %v", err)
449 }
450 if err := tb.Get(ctx, "f", &got); err != nil {
451 t.Fatalf("tb.Get() failed: %v", err)
452 }
453 if !reflect.DeepEqual(got, want) {
454 t.Fatalf("Values do not match: got %v, want %v", got, want)
455 }
456 // Overwrite value.
457 want.I = 6
458 if err := tb.Put(ctx, "f", &want); err != nil {
459 t.Fatalf("tb.Put() failed: %v", err)
460 }
461 if err := tb.Get(ctx, "f", &got); err != nil {
462 t.Fatalf("tb.Get() failed: %v", err)
463 }
464 if !reflect.DeepEqual(got, want) {
465 t.Fatalf("Values do not match: got %v, want %v", got, want)
466 }
Adam Sadovskyc5cc4a32015-06-02 18:44:46 -0700467 if err := tb.Delete(ctx, nosql.Prefix("f")); err != nil {
468 t.Fatalf("tb.Delete() failed: %v", err)
469 }
470 if err := tb.Get(ctx, "f", &got); verror.ErrorID(err) != verror.ErrNoExist.ID {
471 t.Fatalf("r.Get() should have failed: %v", err)
472 }
Adam Sadovskyaba9d502015-04-10 22:06:06 -0700473}
474
475// Tests that Row.{Get,Put,Delete} work as expected.
476func TestRowMethods(t *testing.T) {
Adam Sadovsky13922e32015-05-19 17:39:59 -0700477 ctx, sName, cleanup := tu.SetupOrDie(nil)
478 defer cleanup()
479 a := tu.CreateApp(t, ctx, syncbase.NewService(sName), "a")
480 d := tu.CreateNoSQLDatabase(t, ctx, a, "d")
481 tb := tu.CreateTable(t, ctx, d, "tb")
482
483 r := tb.Row("f")
484 got, want := Foo{}, Foo{I: 4, S: "foo"}
485 if err := r.Get(ctx, &got); verror.ErrorID(err) != verror.ErrNoExist.ID {
486 t.Fatalf("r.Get() should have failed: %v", err)
487 }
488 if err := r.Put(ctx, &want); err != nil {
489 t.Fatalf("r.Put() failed: %v", err)
490 }
491 if err := r.Get(ctx, &got); err != nil {
492 t.Fatalf("r.Get() failed: %v", err)
493 }
494 if !reflect.DeepEqual(got, want) {
495 t.Fatalf("Values do not match: got %v, want %v", got, want)
496 }
497 // Overwrite value.
498 want.I = 6
499 if err := r.Put(ctx, &want); err != nil {
500 t.Fatalf("r.Put() failed: %v", err)
501 }
502 if err := r.Get(ctx, &got); err != nil {
503 t.Fatalf("r.Get() failed: %v", err)
504 }
505 if !reflect.DeepEqual(got, want) {
506 t.Fatalf("Values do not match: got %v, want %v", got, want)
507 }
508 if err := r.Delete(ctx); err != nil {
509 t.Fatalf("r.Delete() failed: %v", err)
510 }
511 if err := r.Get(ctx, &got); verror.ErrorID(err) != verror.ErrNoExist.ID {
512 t.Fatalf("r.Get() should have failed: %v", err)
513 }
Adam Sadovskyaba9d502015-04-10 22:06:06 -0700514}
Sergey Rogulenko445e0412015-06-18 23:06:11 -0700515
516// Test permission checking in Row.{Get,Put,Delete} and
517// Table.{Scan, DeleteRowRange}.
518func TestRowPermissions(t *testing.T) {
Adam Sadovskyda069202015-06-24 12:56:11 -0700519 ctx, clientACtx, sName, rootp, cleanup := tu.SetupOrDieCustom("clientA", "server", nil)
Sergey Rogulenko445e0412015-06-18 23:06:11 -0700520 defer cleanup()
Adam Sadovskyda069202015-06-24 12:56:11 -0700521 clientBCtx := tu.NewCtx(ctx, rootp, "clientB")
Sergey Rogulenko445e0412015-06-18 23:06:11 -0700522 a := tu.CreateApp(t, clientACtx, syncbase.NewService(sName), "a")
523 d := tu.CreateNoSQLDatabase(t, clientACtx, a, "d")
524 tb := tu.CreateTable(t, clientACtx, d, "tb")
525
526 // Permission objects.
Adam Sadovskyda069202015-06-24 12:56:11 -0700527 aAndB := tu.DefaultPerms("root/clientA", "root/clientB")
528 aOnly := tu.DefaultPerms("root/clientA")
529 bOnly := tu.DefaultPerms("root/clientB")
Sergey Rogulenko445e0412015-06-18 23:06:11 -0700530
531 // Set initial permissions.
532 if err := tb.SetPermissions(clientACtx, nosql.Prefix(""), aAndB); err != nil {
533 t.Fatalf("tb.SetPermissions() failed: %v", err)
534 }
535 if err := tb.SetPermissions(clientACtx, nosql.Prefix("a"), aOnly); err != nil {
536 t.Fatalf("tb.SetPermissions() failed: %v", err)
537 }
538 if err := tb.SetPermissions(clientBCtx, nosql.Prefix("b"), bOnly); err != nil {
539 t.Fatalf("tb.SetPermissions() failed: %v", err)
540 }
541
542 // Add some key-value pairs.
543 ra := tb.Row("afoo")
544 rb := tb.Row("bfoo")
545 if err := ra.Put(clientACtx, Foo{}); err != nil {
546 t.Fatalf("ra.Put() failed: %v", err)
547 }
548 if err := rb.Put(clientBCtx, Foo{}); err != nil {
549 t.Fatalf("rb.Put() failed: %v", err)
550 }
551
552 // Check A doesn't have access to 'b'.
553 if err := rb.Get(clientACtx, &Foo{}); verror.ErrorID(err) != verror.ErrNoAccess.ID {
554 t.Fatalf("rb.Get() should have failed: %v", err)
555 }
556 if err := rb.Put(clientACtx, Foo{}); verror.ErrorID(err) != verror.ErrNoAccess.ID {
557 t.Fatalf("rb.Put() should have failed: %v", err)
558 }
559 if err := rb.Delete(clientACtx); verror.ErrorID(err) != verror.ErrNoAccess.ID {
560 t.Fatalf("rb.Delete() should have failed: %v", err)
561 }
562 // Test Table.Delete and Scan.
563 if err := tb.Delete(clientACtx, nosql.Prefix("")); verror.ErrorID(err) != verror.ErrNoAccess.ID {
564 t.Fatalf("tb.Delete should have failed: %v", err)
565 }
566 s := tb.Scan(clientACtx, nosql.Prefix(""))
567 if !s.Advance() {
568 t.Fatalf("Stream should have advanced: %v", s.Err())
569 }
570 if s.Key() != "afoo" {
571 t.Fatalf("Unexpected key: got %q, want %q", s.Key(), "afoo")
572 }
573 if s.Advance() {
574 t.Fatalf("Stream advanced unexpectedly")
575 }
576 if err := s.Err(); verror.ErrorID(err) != verror.ErrNoAccess.ID {
577 t.Fatalf("Unexpected stream error: %v", err)
578 }
579}