sensorlog_lite: Device and stream VDL types.
Basic VDL types for stream configuration.
Support for types storing data in both key and value.
Change-Id: Ib3a904e27e05128819fdff75e9100c5fe1626b46
diff --git a/go/src/v.io/x/sensorlog/internal/config/defaults.go b/go/src/v.io/x/sensorlog/internal/config/defaults.go
index 1854d83..1ce9f9a 100644
--- a/go/src/v.io/x/sensorlog/internal/config/defaults.go
+++ b/go/src/v.io/x/sensorlog/internal/config/defaults.go
@@ -16,12 +16,8 @@
DBName = "sldb"
SyncPriority = 42
-
- StreamDefTable = "strdef"
)
-var AllTables = []string{StreamDefTable}
-
func SyncgroupName(publishService, devId string) string {
return naming.Join(publishService, "%%sync", "sllite", "dev", devId)
}
diff --git a/go/src/v.io/x/sensorlog/internal/measure/syncgroup.go b/go/src/v.io/x/sensorlog/internal/measure/syncgroup.go
index 871e619..8f58bb0 100644
--- a/go/src/v.io/x/sensorlog/internal/measure/syncgroup.go
+++ b/go/src/v.io/x/sensorlog/internal/measure/syncgroup.go
@@ -16,6 +16,8 @@
"v.io/v23/syncbase/nosql"
"v.io/v23/verror"
"v.io/x/sensorlog_lite/internal/config"
+ "v.io/x/sensorlog_lite/internal/sbmodel"
+ "v.io/x/sensorlog_lite/internal/sbmodel/keyutil"
"v.io/x/sensorlog_lite/internal/sbutil"
)
@@ -26,6 +28,10 @@
// retried with different parameters for the same devId, otherwise behaviour
// is unspecified.
func InitSyncgroup(ctx *context.T, db nosql.Database, devId, admin, sgPublishSb string, sgMountTables []string) error {
+ if err := keyutil.ValidateId(devId); err != nil {
+ return fmt.Errorf("invalid devId: %v", err)
+ }
+
sgName := config.SyncgroupName(sgPublishSb, devId)
// Check for syncgroup. If it already exists, we have nothing to do.
if sgs, err := db.GetSyncgroupNames(ctx); err != nil {
@@ -49,7 +55,7 @@
// StreamDef : <devId>
// Admin client has full permissions, measured drops to readonly.
prefixStreamDef := nosql_wire.SyncgroupPrefix{
- TableName: config.StreamDefTable,
+ TableName: sbmodel.KStreamDef{}.Table(),
RowPrefix: devId,
}
aclStreamDef := access.Permissions{}
diff --git a/go/src/v.io/x/sensorlog/internal/measure/syncgroup_test.go b/go/src/v.io/x/sensorlog/internal/measure/syncgroup_test.go
index 24ba12f..f38ef39 100644
--- a/go/src/v.io/x/sensorlog/internal/measure/syncgroup_test.go
+++ b/go/src/v.io/x/sensorlog/internal/measure/syncgroup_test.go
@@ -5,14 +5,16 @@
package measure_test
import (
+ "bytes"
"reflect"
"testing"
- "v.io/v23/verror"
+ "v.io/v23/security/access"
_ "v.io/x/ref/runtime/factories/generic"
sbtu "v.io/x/ref/services/syncbase/testutil"
"v.io/x/sensorlog_lite/internal/config"
"v.io/x/sensorlog_lite/internal/measure"
+ "v.io/x/sensorlog_lite/internal/sbmodel"
"v.io/x/sensorlog_lite/internal/sbutil"
)
@@ -21,7 +23,7 @@
defer cleanup()
// Open app/db (create both) as measured.
- db, err := sbutil.CreateOrOpenDB(ctxMeasured, sbName, config.AllTables)
+ db, err := sbutil.CreateOrOpenDB(ctxMeasured, sbName, sbmodel.MeasuredTables)
if err != nil {
t.Fatalf("CreateOrOpenDB should have succeeded, got error: %v", err)
}
@@ -48,8 +50,20 @@
}
// measured should have dropped privileges on <StreamDefTable>/<devId>.
- sgDataRow := db.Table(config.StreamDefTable).Row(devId + "$" + "foo")
- if err := sgDataRow.Put(ctxMeasured, "bar"); verror.ErrorID(err) != verror.ErrNoAccess.ID {
- t.Errorf("Put by measured should have failed with ErrNoAccess, got: %v", err)
+ expectPerms, err := access.ReadPermissions(bytes.NewBufferString(`{
+ "Admin":{"In":["root/two"]},
+ "Read":{"In":["root/two", "root/one"]},
+ "Write":{"In":["root/two"]},
+ "Debug":{"In":["root/two"]},
+ "Resolve":{"In":["root/two", "root/one"]}
+ }`))
+ if err != nil {
+ t.Fatalf("ReadPermissions should have succeeded, got error: %v", err)
+ }
+ sgDataTable := db.Table(sbmodel.KStreamDef{}.Table())
+ if gotPerms, err := sgDataTable.GetPrefixPermissions(ctxMeasured, devId); err != nil {
+ t.Errorf("GetPrefixPermissions failed: %v", err)
+ } else if got, want := gotPerms[0].Perms.Normalize(), expectPerms.Normalize(); !reflect.DeepEqual(got, want) {
+ t.Errorf("Unexpected permissions on streamdef/<devId>: got %v, want %v", got, want)
}
}
diff --git a/go/src/v.io/x/sensorlog/internal/sbmodel/keyutil/keyutil.go b/go/src/v.io/x/sensorlog/internal/sbmodel/keyutil/keyutil.go
new file mode 100644
index 0000000..408f8c4
--- /dev/null
+++ b/go/src/v.io/x/sensorlog/internal/sbmodel/keyutil/keyutil.go
@@ -0,0 +1,51 @@
+// Copyright 2015 The Vanadium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Utilities for building and parsing Sensor Log data keys.
+package keyutil
+
+import (
+ "crypto/rand"
+ "encoding/hex"
+ "fmt"
+ "strings"
+)
+
+const Sep = '$'
+
+// Join joins key parts into key.
+func Join(parts ...string) string {
+ return strings.Join(parts, string(Sep))
+}
+
+// Split splits key into parts and verifies that the number of parts matches
+// the expected number, returning an error otherwise.
+func Split(key string, expectParts int) ([]string, error) {
+ parts := strings.Split(key, string(Sep))
+ if gotParts := len(parts); expectParts != gotParts {
+ return nil, fmt.Errorf("invalid key %q: expected %d parts, got %d", key, expectParts, gotParts)
+ }
+ return parts, nil
+}
+
+// ValidateId returns an error if the argument is not a valid identifier.
+func ValidateId(id string) error {
+ if id == "" {
+ return fmt.Errorf("cannot be empty")
+ }
+ if strings.Contains(id, string(Sep)) {
+ return fmt.Errorf("cannot contain %q", Sep)
+ }
+ return nil
+}
+
+// UUID generates a random UUID.
+func UUID() string {
+ uuid := make([]byte, 16)
+ if _, err := rand.Read(uuid); err != nil {
+ panic(fmt.Errorf("rng failed: %v", err))
+ }
+ // TODO(ivanpi): Use base64 once Syncbase keys are less restricted.
+ return hex.EncodeToString(uuid)
+}
diff --git a/go/src/v.io/x/sensorlog/internal/sbmodel/types.go b/go/src/v.io/x/sensorlog/internal/sbmodel/types.go
new file mode 100644
index 0000000..a8579c8
--- /dev/null
+++ b/go/src/v.io/x/sensorlog/internal/sbmodel/types.go
@@ -0,0 +1,65 @@
+// Copyright 2015 The Vanadium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Implements PersistentDataKey for each K<T> type, as described in types.vdl.
+
+package sbmodel
+
+import (
+ "v.io/x/sensorlog_lite/internal/sbmodel/keyutil"
+)
+
+// PersistentDataKey is a type encapsulating data from the row key of a
+// top-level value type persisted to Syncbase.
+type PersistentDataKey interface {
+ // Table returns the name of the Syncbase table for the data type.
+ Table() string
+ // Key returns the row key for the value.
+ Key() string
+ // Parse parses the row key for the value into self. Returns an error if key
+ // is malformed.
+ Parse(key string) error
+}
+
+// devicecfg : <DevId>
+func (_ KDeviceCfg) Table() string { return "devicecfg" }
+func (k *KDeviceCfg) Key() string { return keyutil.Join(k.DevId) }
+func (k *KDeviceCfg) Parse(key string) error {
+ parts, err := keyutil.Split(key, 1)
+ if err != nil {
+ return err
+ }
+ k.DevId = parts[0]
+ return nil
+}
+
+// streamdef : <DevId>/<StreamId>
+func (_ KStreamDef) Table() string { return "streamdef" }
+func (k *KStreamDef) Key() string { return keyutil.Join(k.DevId, k.StreamId) }
+func (k *KStreamDef) Parse(key string) error {
+ parts, err := keyutil.Split(key, 2)
+ if err != nil {
+ return err
+ }
+ k.DevId, k.StreamId = parts[0], parts[1]
+ return nil
+}
+
+// TableSpec defines a Syncbase table, encapsulating a key prototype and
+// permissions.
+type TableSpec struct {
+ Prototype PersistentDataKey
+ ReadOnly bool
+}
+
+// All top-level types persisted to master device Syncbase.
+var MasterTables = []TableSpec{
+ {Prototype: &KDeviceCfg{}},
+ {Prototype: &KStreamDef{}},
+}
+
+// All top-level types persisted to measured Syncbase.
+var MeasuredTables = []TableSpec{
+ {Prototype: &KStreamDef{}, ReadOnly: true},
+}
diff --git a/go/src/v.io/x/sensorlog/internal/sbmodel/types.vdl b/go/src/v.io/x/sensorlog/internal/sbmodel/types.vdl
new file mode 100644
index 0000000..4ddee43
--- /dev/null
+++ b/go/src/v.io/x/sensorlog/internal/sbmodel/types.vdl
@@ -0,0 +1,39 @@
+// Copyright 2015 The Vanadium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Syncbase data model for Sensor Log.
+//
+// Every type <T> stored in Syncbase is defined as a pair of types, K<T> and
+// V<T>, representing data stored in the key and value, respectively, in a
+// single table. K<T> types satisfy the PersistentDataKey interface, supporting
+// conversion to and from the row key.
+package sbmodel
+
+// devicecfg : <DevId>
+// Measuring device handle. Master only.
+type VDeviceCfg struct {
+ // Human-readable, not necessarily unique description of the device.
+ Desc string
+ // Syncbase instance publishing the syncgroup created by the device.
+ SgPublishSb string
+}
+
+type KDeviceCfg struct {
+ DevId string
+}
+
+// streamdef : <DevId>/<StreamId>
+// Configures a stream of data to be measured.
+// TODO(ivanpi): Add actual sampling script and parameters.
+type VStreamDef struct {
+ // Human-readable, not necessarily unique description of the stream.
+ Desc string
+ // Flag to start and stop sampling.
+ Enabled bool
+}
+
+type KStreamDef struct {
+ DevId string
+ StreamId string
+}
diff --git a/go/src/v.io/x/sensorlog/internal/sbmodel/types.vdl.go b/go/src/v.io/x/sensorlog/internal/sbmodel/types.vdl.go
new file mode 100644
index 0000000..355db3c
--- /dev/null
+++ b/go/src/v.io/x/sensorlog/internal/sbmodel/types.vdl.go
@@ -0,0 +1,74 @@
+// Copyright 2015 The Vanadium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// This file was auto-generated by the vanadium vdl tool.
+// Source: types.vdl
+
+// Syncbase data model for Sensor Log.
+//
+// Every type <T> stored in Syncbase is defined as a pair of types, K<T> and
+// V<T>, representing data stored in the key and value, respectively, in a
+// single table. K<T> types satisfy the PersistentDataKey interface, supporting
+// conversion to and from the row key.
+package sbmodel
+
+import (
+ // VDL system imports
+ "v.io/v23/vdl"
+)
+
+// devicecfg : <DevId>
+// Measuring device handle. Master only.
+type VDeviceCfg struct {
+ // Human-readable, not necessarily unique description of the device.
+ Desc string
+ // Syncbase instance publishing the syncgroup created by the device.
+ SgPublishSb string
+}
+
+func (VDeviceCfg) __VDLReflect(struct {
+ Name string `vdl:"v.io/x/sensorlog_lite/internal/sbmodel.VDeviceCfg"`
+}) {
+}
+
+type KDeviceCfg struct {
+ DevId string
+}
+
+func (KDeviceCfg) __VDLReflect(struct {
+ Name string `vdl:"v.io/x/sensorlog_lite/internal/sbmodel.KDeviceCfg"`
+}) {
+}
+
+// streamdef : <DevId>/<StreamId>
+// Configures a stream of data to be measured.
+// TODO(ivanpi): Add actual sampling script and parameters.
+type VStreamDef struct {
+ // Human-readable, not necessarily unique description of the stream.
+ Desc string
+ // Flag to start and stop sampling.
+ Enabled bool
+}
+
+func (VStreamDef) __VDLReflect(struct {
+ Name string `vdl:"v.io/x/sensorlog_lite/internal/sbmodel.VStreamDef"`
+}) {
+}
+
+type KStreamDef struct {
+ DevId string
+ StreamId string
+}
+
+func (KStreamDef) __VDLReflect(struct {
+ Name string `vdl:"v.io/x/sensorlog_lite/internal/sbmodel.KStreamDef"`
+}) {
+}
+
+func init() {
+ vdl.Register((*VDeviceCfg)(nil))
+ vdl.Register((*KDeviceCfg)(nil))
+ vdl.Register((*VStreamDef)(nil))
+ vdl.Register((*KStreamDef)(nil))
+}
diff --git a/go/src/v.io/x/sensorlog/internal/sbmodel/types_test.go b/go/src/v.io/x/sensorlog/internal/sbmodel/types_test.go
new file mode 100644
index 0000000..12453de
--- /dev/null
+++ b/go/src/v.io/x/sensorlog/internal/sbmodel/types_test.go
@@ -0,0 +1,82 @@
+// Copyright 2015 The Vanadium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package sbmodel_test
+
+import (
+ "reflect"
+ "testing"
+
+ "v.io/x/sensorlog_lite/internal/sbmodel"
+ "v.io/x/sensorlog_lite/internal/sbmodel/keyutil"
+)
+
+type keyTest interface {
+ Run(t *testing.T, keyPrototype sbmodel.PersistentDataKey)
+}
+
+// validKeyTest verifies that the key is correctly parsed and built.
+type validKeyTest struct {
+ keyStr string
+ keyParsed sbmodel.PersistentDataKey
+}
+
+func (kt *validKeyTest) Run(t *testing.T, keyPrototype sbmodel.PersistentDataKey) {
+ if err := keyPrototype.Parse(kt.keyStr); err != nil {
+ t.Errorf("key %q parse failed: %v", kt.keyStr, err)
+ return
+ }
+ if got, want := keyPrototype, kt.keyParsed; !reflect.DeepEqual(got, want) {
+ t.Errorf("incorrect key parse: got %v, want %v", got, want)
+ }
+ if got, want := kt.keyParsed.Key(), kt.keyStr; got != want {
+ t.Errorf("incorrect key build: got %s, want %s", got, want)
+ }
+}
+
+// invalidKeyTest verifies that malformed key parsing fails.
+type invalidKeyTest struct {
+ keyStr string
+}
+
+func (kt *invalidKeyTest) Run(t *testing.T, keyPrototype sbmodel.PersistentDataKey) {
+ if err := keyPrototype.Parse(kt.keyStr); err == nil {
+ t.Errorf("key %q parse should have failed", kt.keyStr)
+ }
+}
+
+func TestDeviceCfgKeys(t *testing.T) {
+ tests := []keyTest{
+ &validKeyTest{
+ keyStr: keyutil.Join("foo"),
+ keyParsed: &sbmodel.KDeviceCfg{
+ DevId: "foo",
+ },
+ },
+ &invalidKeyTest{
+ keyStr: keyutil.Join("foo", "bar"),
+ },
+ }
+ for _, kt := range tests {
+ kt.Run(t, &sbmodel.KDeviceCfg{})
+ }
+}
+
+func TestStreamDefKeys(t *testing.T) {
+ tests := []keyTest{
+ &validKeyTest{
+ keyStr: keyutil.Join("pc", "cputemp"),
+ keyParsed: &sbmodel.KStreamDef{
+ DevId: "pc",
+ StreamId: "cputemp",
+ },
+ },
+ &invalidKeyTest{
+ keyStr: keyutil.Join("pc"),
+ },
+ }
+ for _, kt := range tests {
+ kt.Run(t, &sbmodel.KStreamDef{})
+ }
+}
diff --git a/go/src/v.io/x/sensorlog/internal/sbutil/syncbase.go b/go/src/v.io/x/sensorlog/internal/sbutil/syncbase.go
index 8c7c708..1bc1784 100644
--- a/go/src/v.io/x/sensorlog/internal/sbutil/syncbase.go
+++ b/go/src/v.io/x/sensorlog/internal/sbutil/syncbase.go
@@ -14,17 +14,24 @@
"v.io/v23/syncbase/nosql"
"v.io/v23/verror"
"v.io/x/sensorlog_lite/internal/config"
+ "v.io/x/sensorlog_lite/internal/sbmodel"
)
// CreateOrOpenDB opens the Sensor Log database hosted on specified Syncbase
// instance, creating it if missing, initializing specified tables.
-func CreateOrOpenDB(ctx *context.T, sbService string, tables []string) (nosql.Database, error) {
+func CreateOrOpenDB(ctx *context.T, sbService string, tables []sbmodel.TableSpec) (nosql.Database, error) {
aclFull := access.Permissions{}
- // Allow everyone to resolve app/database to allow joining syncgroups.
+ // Allow everyone to resolve to allow joining syncgroups.
AddPermsForPattern(&aclFull, string(security.AllPrincipals), access.Resolve)
// Restrict other permissions to self.
AddPermsForPrincipal(&aclFull, v23.GetPrincipal(ctx), access.Read, access.Write, access.Admin, access.Debug)
+ aclReadOnly := access.Permissions{}
+ // Allow everyone to resolve to allow joining syncgroups.
+ AddPermsForPattern(&aclReadOnly, string(security.AllPrincipals), access.Resolve)
+ // Restrict other permissions to self, except Write.
+ AddPermsForPrincipal(&aclReadOnly, v23.GetPrincipal(ctx), access.Read, access.Admin, access.Debug)
+
sbs := syncbase.NewService(sbService)
app := sbs.App(config.AppName)
if err := createIfMissing(ctx, app, aclFull); err != nil {
@@ -38,9 +45,13 @@
}
// TODO(ivanpi): Add table schemas when available.
- for _, tn := range tables {
- tb := db.Table(tn)
- if err := createIfMissing(ctx, tb, aclFull); err != nil {
+ for _, ts := range tables {
+ tb := db.Table(ts.Prototype.Table())
+ acl := aclReadOnly
+ if !ts.ReadOnly {
+ acl = aclFull
+ }
+ if err := createIfMissing(ctx, tb, acl); err != nil {
return nil, err
}
}
diff --git a/go/src/v.io/x/sensorlog/internal/sbutil/syncbase_test.go b/go/src/v.io/x/sensorlog/internal/sbutil/syncbase_test.go
index 40c2016..543daa5 100644
--- a/go/src/v.io/x/sensorlog/internal/sbutil/syncbase_test.go
+++ b/go/src/v.io/x/sensorlog/internal/sbutil/syncbase_test.go
@@ -13,6 +13,7 @@
"v.io/v23/verror"
_ "v.io/x/ref/runtime/factories/generic"
sbtu "v.io/x/ref/services/syncbase/testutil"
+ "v.io/x/sensorlog_lite/internal/sbmodel"
"v.io/x/sensorlog_lite/internal/sbutil"
)
@@ -21,19 +22,17 @@
defer cleanup()
ctxGuest := sbtu.NewCtx(ctxOwner, rootPrincipal, "two")
- mockTables := []string{"tfoo", "tbar"}
-
// Try to open app/db (create both) as guest, fail with ErrNoAccess.
- if _, err := sbutil.CreateOrOpenDB(ctxGuest, sbName, mockTables); verror.ErrorID(err) != verror.ErrNoAccess.ID {
+ if _, err := sbutil.CreateOrOpenDB(ctxGuest, sbName, sbmodel.MasterTables); verror.ErrorID(err) != verror.ErrNoAccess.ID {
t.Errorf("CreateOrOpenDB should have failed with ErrNoAccess, got error: %v", err)
}
// Open app/db (create both) as owner.
- dbOwner, err := sbutil.CreateOrOpenDB(ctxOwner, sbName, mockTables)
+ dbOwner, err := sbutil.CreateOrOpenDB(ctxOwner, sbName, sbmodel.MasterTables)
if err != nil {
t.Fatalf("CreateOrOpenDB should have succeeded, got error: %v", err)
}
// Open existing app/db as guest.
- if _, err := sbutil.CreateOrOpenDB(ctxGuest, sbName, mockTables); err != nil {
+ if _, err := sbutil.CreateOrOpenDB(ctxGuest, sbName, sbmodel.MasterTables); err != nil {
t.Errorf("CreateOrOpenDB should have succeeded, got error: %v", err)
}
// Destroy db (but not app) to simulate interrupted creation.
@@ -41,16 +40,16 @@
t.Errorf("dbOwner.Destroy should have succeeded, got error: %v", err)
}
// Try to open app/db (create db) as guest, fail with ErrNoAccess.
- if _, err := sbutil.CreateOrOpenDB(ctxGuest, sbName, mockTables); verror.ErrorID(err) != verror.ErrNoAccess.ID {
+ if _, err := sbutil.CreateOrOpenDB(ctxGuest, sbName, sbmodel.MasterTables); verror.ErrorID(err) != verror.ErrNoAccess.ID {
t.Errorf("CreateOrOpenDB should have failed with ErrNoAccess, got error: %v", err)
}
// Open app/db (recreate db) as owner.
- dbOwner, err = sbutil.CreateOrOpenDB(ctxOwner, sbName, mockTables)
+ dbOwner, err = sbutil.CreateOrOpenDB(ctxOwner, sbName, sbmodel.MasterTables)
if err != nil {
t.Fatalf("CreateOrOpenDB should have succeeded, got error: %v", err)
}
// Open recreated app/db as guest.
- dbGuest, err := sbutil.CreateOrOpenDB(ctxGuest, sbName, mockTables)
+ dbGuest, err := sbutil.CreateOrOpenDB(ctxGuest, sbName, sbmodel.MasterTables)
if err != nil {
t.Errorf("CreateOrOpenDB should have succeeded, got error: %v", err)
}
@@ -71,10 +70,58 @@
t.Errorf("Unexpected database permissions: got %v, want %v", got, want)
}
// Check that all tables exist.
- for _, tn := range mockTables {
- tb := dbGuest.Table(tn)
+ for _, ts := range sbmodel.MasterTables {
+ tb := dbGuest.Table(ts.Prototype.Table())
if exists, err := tb.Exists(ctxGuest); err != nil || !exists {
t.Errorf("Expected table %s to exist, got: %v (error: %v)", tb.Name(), exists, err)
}
}
}
+
+func TestTablePermissions(t *testing.T) {
+ _, ctxOwner, sbName, _, cleanup := sbtu.SetupOrDieCustom("one", "one/sb", nil)
+ defer cleanup()
+
+ // Open app/db (create both) as owner.
+ dbOwner, err := sbutil.CreateOrOpenDB(ctxOwner, sbName, sbmodel.MeasuredTables)
+ if err != nil {
+ t.Fatalf("CreateOrOpenDB should have succeeded, got error: %v", err)
+ }
+
+ expectPermsFull, err := access.ReadPermissions(bytes.NewBufferString(`{
+ "Admin":{"In":["root/one"]},
+ "Read":{"In":["root/one"]},
+ "Write":{"In":["root/one"]},
+ "Debug":{"In":["root/one"]},
+ "Resolve":{"In":["..."]}
+ }`))
+ if err != nil {
+ t.Fatalf("ReadPermissions should have succeeded, got error: %v", err)
+ }
+ expectPermsReadOnly, err := access.ReadPermissions(bytes.NewBufferString(`{
+ "Admin":{"In":["root/one"]},
+ "Read":{"In":["root/one"]},
+ "Debug":{"In":["root/one"]},
+ "Resolve":{"In":["..."]}
+ }`))
+ if err != nil {
+ t.Fatalf("ReadPermissions should have succeeded, got error: %v", err)
+ }
+
+ // Check that all tables have correct permissions (full or readonly).
+ for _, ts := range sbmodel.MeasuredTables {
+ tb := dbOwner.Table(ts.Prototype.Table())
+ if exists, err := tb.Exists(ctxOwner); err != nil || !exists {
+ t.Errorf("Expected table %s to exist, got: %v (error: %v)", tb.Name(), exists, err)
+ }
+ want := expectPermsFull
+ if ts.ReadOnly {
+ want = expectPermsReadOnly
+ }
+ if got, err := tb.GetPermissions(ctxOwner); err != nil {
+ t.Errorf("GetPermissions should have succeeded, got error: %v", err)
+ } else if got, want = got.Normalize(), want.Normalize(); !reflect.DeepEqual(got, want) {
+ t.Errorf("Unexpected table %s permissions: got %v, want %v", tb.Name(), got, want)
+ }
+ }
+}
diff --git a/go/src/v.io/x/sensorlog/measured/measured.go b/go/src/v.io/x/sensorlog/measured/measured.go
index ef36609..1e442db 100644
--- a/go/src/v.io/x/sensorlog/measured/measured.go
+++ b/go/src/v.io/x/sensorlog/measured/measured.go
@@ -18,6 +18,7 @@
_ "v.io/x/ref/runtime/factories/generic"
"v.io/x/sensorlog_lite/internal/config"
"v.io/x/sensorlog_lite/internal/measure"
+ "v.io/x/sensorlog_lite/internal/sbmodel"
"v.io/x/sensorlog_lite/internal/sbutil"
)
@@ -51,7 +52,7 @@
}
publishMts := v23.GetNamespace(ctx).Roots()
- db, err := sbutil.CreateOrOpenDB(ctx, *flagSbService, config.AllTables)
+ db, err := sbutil.CreateOrOpenDB(ctx, *flagSbService, sbmodel.MeasuredTables)
if err != nil {
vlog.Errorf("Failed opening Syncbase db: %v", err)
return 1