| // Copyright 2016 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 leveldb_test |
| |
| import ( |
| "crypto/rand" |
| "fmt" |
| "log" |
| "testing" |
| "time" |
| |
| "v.io/v23/context" |
| "v.io/v23/security" |
| "v.io/v23/security/access" |
| "v.io/v23/syncbase" |
| "v.io/x/ref/lib/stats" |
| _ "v.io/x/ref/runtime/factories/generic" |
| tu "v.io/x/ref/services/syncbase/testutil" |
| ) |
| |
| // In this file we do integration tests of the leveldb stats via the public |
| // Syncbase API. For lower level tests see the stats_test.go file. |
| |
| func TestEmpty(t *testing.T) { |
| _, serverName, cleanup := tu.SetupOrDie(nil) |
| defer cleanup() |
| |
| since := time.Now() |
| syncbase.NewService(serverName) |
| |
| count := 0 |
| for got := range statsValues("service/*/*", since) { |
| count++ |
| |
| // All stats values should be zero (see stats_test.go) |
| if got.(int64) != 0 { |
| t.Errorf("Got %v, want 0", got) |
| } |
| } |
| // Want 2 stats keys for the service |
| if count != 2 { |
| t.Errorf("Got %d service stats keys, want 2", count) |
| } |
| |
| count = 0 |
| for got := range statsValues("blobmap/*/*", since) { |
| count++ |
| |
| // All stats values should be zero (see stats_test.go) |
| if got.(int64) != 0 { |
| t.Errorf("Got %v, want 0", got) |
| } |
| } |
| // Want 2 stats keys for the blobmap |
| if count != 2 { |
| t.Errorf("Got %d blobmap stats keys, want 2", count) |
| } |
| |
| for range statsValues("db/v_io_a_xyz/*/*/*", since) { |
| t.Error("Expected no database-specific stats") |
| } |
| } |
| |
| func TestWithMultipleDbs(t *testing.T) { |
| ctx, serverName, cleanup := tu.SetupOrDie(nil) |
| defer cleanup() |
| |
| since := time.Now() |
| service := syncbase.NewService(serverName) |
| tu.CreateDatabase(t, ctx, service, "empty_db_0") |
| tu.CreateDatabase(t, ctx, service, "empty_db_1") |
| tu.CreateDatabase(t, ctx, service, "empty_db_2") |
| |
| count := 0 |
| for got := range statsValues("service/*/*", since) { |
| count++ |
| |
| // All stats values should be zero (see stats_test.go) |
| if got.(int64) != 0 { |
| t.Errorf("Got %v, want 0", got) |
| } |
| } |
| // Want 2 stats keys for the service |
| if count != 2 { |
| t.Errorf("Got %d service stats keys, want 2", count) |
| } |
| |
| count = 0 |
| for got := range statsValues("blobmap/*/*", since) { |
| count++ |
| |
| // All stats values should be zero (see stats_test.go) |
| if got.(int64) != 0 { |
| t.Errorf("Got %v, want 0", got) |
| } |
| } |
| // Want 2 stats keys for the blobmap |
| if count != 2 { |
| t.Errorf("Got %d blobmap stats keys, want 2", count) |
| } |
| |
| count = 0 |
| for got := range statsValues("db/v_io_a_xyz/*/*/*", since) { |
| count++ |
| |
| // All stats values should be zero (see stats_test.go) |
| if got.(int64) != 0 { |
| t.Errorf("Got %v, want 0", got) |
| } |
| } |
| // Want 2 stats keys per each of 3 DBs |
| if count != 6 { |
| t.Errorf("Got %d DB stats keys, want 6", count) |
| } |
| } |
| |
| func TestWithLotsOfData(t *testing.T) { |
| ctx, serverName, cleanup := tu.SetupOrDie(nil) |
| defer cleanup() |
| |
| since := time.Now() |
| service := syncbase.NewService(serverName) |
| db := tu.CreateDatabase(t, ctx, service, "big_db") |
| |
| write100MB(ctx, db) |
| |
| // Expect at least 50 MB (see stats_test.go) |
| fileBytes := <-statsValues("db/v_io_a_xyz/big_db/*/filesystem_bytes", since) |
| if fileBytes.(int64) < 50*1024*1024 { |
| t.Errorf("Got %v, want more than 50 MB", fileBytes.(int64)) |
| } |
| // Expect 25 or more (see stats_test.go) |
| fileCount := <-statsValues("db/v_io_a_xyz/big_db/*/file_count", since) |
| if fileCount.(int64) < 25 { |
| t.Errorf("Got %v, want 25 or more", fileCount.(int64)) |
| } |
| } |
| |
| // statsValues returns a channel with all the values since the given time of the |
| // sync keys that match the given glob under the root "syncbase/leveldb/". |
| func statsValues(pattern string, since time.Time) <-chan interface{} { |
| ch := make(chan interface{}) |
| go func() { |
| iter := stats.Glob("syncbase/leveldb/", pattern, since, true) |
| for iter.Advance() { |
| if err := iter.Err(); err != nil { |
| panic(err) |
| } |
| if iter.Value().Value == nil { |
| log.Printf("Ignoring empty stats %q", iter.Value().Key) |
| } else { |
| ch <- iter.Value().Value |
| } |
| } |
| close(ch) |
| }() |
| return ch |
| } |
| |
| // Write 100 kB each to 1024 keys, returning keys written. |
| func write100MB(ctx *context.T, db syncbase.Database) { |
| coll := db.Collection(ctx, "the_collection") |
| err := coll.Create(ctx, permissions) |
| if err != nil { |
| panic(err) |
| } |
| |
| hundredKB := make([]byte, 100*1024) |
| |
| // Write 1024 X 100 KB (100 MB). |
| for i := 0; i < 1024; i++ { |
| rand.Read(hundredKB) // Randomize so it won't compress. |
| key := fmt.Sprintf("foo-%d", i) |
| err := coll.Put(ctx, key, hundredKB) |
| if err != nil { |
| panic(err) |
| } |
| } |
| return |
| } |
| |
| var ( |
| allAccess = access.AccessList{In: []security.BlessingPattern{"..."}} |
| permissions = access.Permissions{ |
| "Admin": allAccess, |
| "Write": allAccess, |
| "Read": allAccess, |
| "Resolve": allAccess, |
| "Debug": allAccess, |
| } |
| ) |