blob: 71172b0ac1530c27f5d9fc31085bfe843428bc1a [file] [log] [blame]
// 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,
}
)