blob: bcafcb77b733fcfc6b9592433ee3e448a5507d68 [file] [log] [blame]
// 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 nosql_test
import (
"testing"
wire "v.io/syncbase/v23/services/syncbase/nosql"
"v.io/syncbase/v23/syncbase"
tu "v.io/syncbase/v23/syncbase/testutil"
"v.io/v23/context"
)
// Tests schema checking logic within App.NoSQLDatabase() method.
// This test as following steps:
// 1) Call NoSQLDatabase() for a non existent db.
// 2) Create the database, and verify if Schema got stored properly.
// 3) Call UpgradeIfOutdated() to make sure that the method is no-op and is
// able to read the schema from db.
// 4) Call NoSQLDatabase() on the same db to create a new handle with an
// upgraded schema, call UpgradeIfOutdated() and check if SchemaUpgrader
// is called and if the new schema is stored appropriately.
func TestSchemaCheck(t *testing.T) {
ctx, sName, cleanup := tu.SetupOrDie(nil)
defer cleanup()
a := tu.CreateApp(t, ctx, syncbase.NewService(sName), "a")
schema := tu.DefaultSchema()
mockUpgrader := schema.Upgrader.(*tu.MockSchemaUpgrader)
db1 := a.NoSQLDatabase("db1", schema)
// Verify that calling Upgrade on a non existing database does not throw
// errors.
_, err := db1.UpgradeIfOutdated(ctx)
if err != nil {
t.Fatalf("db1.UpgradeIfOutdated() failed: %v", err)
}
if mockUpgrader.CallCount > 0 {
t.Fatal("Call to upgrader was not expected.")
}
// Create db1, this step also stores the schema provided above
if err := db1.Create(ctx, nil); err != nil {
t.Fatalf("db1.Create() failed: %v", err)
}
// verify if schema was stored as part of create
if _, err := getSchemaMetadata(ctx, db1.FullName()); err != nil {
t.Fatalf("Failed to lookup schema after create: %v", err)
}
// Make redundant call to Upgrade to verify that it is a no-op
result, err1 := db1.UpgradeIfOutdated(ctx)
if result {
t.Fatalf("db1.UpgradeIfOutdated() should not return true")
}
if err1 != nil {
t.Fatalf("db1.UpgradeIfOutdated() failed: %v", err1)
}
if mockUpgrader.CallCount > 0 {
t.Fatal("Call to upgrader was not expected.")
}
// try to make a new database object for the same database but this time
// with a new schema version
schema.Metadata.Version = 1
rule := wire.CrRule{"table1", "foo", "", wire.ResolverTypeLastWins}
policy := wire.CrPolicy{
Rules: []wire.CrRule{rule},
}
schema.Metadata.Policy = policy
otherdb1 := a.NoSQLDatabase("db1", schema)
otherresult, othererr := otherdb1.UpgradeIfOutdated(ctx)
if !otherresult {
t.Fatalf("otherdb1.UpgradeIfOutdated() expected to return true")
}
if othererr != nil {
t.Fatalf("otherdb1.UpgradeIfOutdated() failed: %v", othererr)
}
if mockUpgrader.CallCount != 1 {
t.Fatalf("Unexpected number of calls to upgrader. Expected: %d, Actual: %d.", 1, mockUpgrader.CallCount)
}
// check if the contents of SchemaMetadata are correctly stored in the db.
metadata, err3 := getSchemaMetadata(ctx, otherdb1.FullName())
if err3 != nil {
t.Fatalf("GetSchemaMetadata failed: %v", err3)
}
if metadata.Version != 1 {
t.Fatalf("Unexpected version number: %d", metadata.Version)
}
if len(metadata.Policy.Rules) != 1 {
t.Fatalf("Unexpected number of rules: %d", len(metadata.Policy.Rules))
}
if metadata.Policy.Rules[0] != rule {
t.Fatalf("Unexpected number of rules: %d", len(metadata.Policy.Rules))
}
}
func getSchemaMetadata(ctx *context.T, dbName string) (wire.SchemaMetadata, error) {
return wire.DatabaseClient(dbName).GetSchemaMetadata(ctx)
}