// 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

import (
	"reflect"
	"testing"

	"v.io/v23"
	"v.io/v23/rpc"
	"v.io/v23/security"
	"v.io/v23/security/access"
	_ "v.io/x/ref/runtime/factories/generic"
	"v.io/x/ref/services/syncbase/clock"
	"v.io/x/ref/services/syncbase/server/util"
	"v.io/x/ref/services/syncbase/server/watchable"
	"v.io/x/ref/services/syncbase/store"
	"v.io/x/ref/services/syncbase/store/memstore"
	"v.io/x/ref/test"
	"v.io/x/ref/test/testutil"
)

type mockCall struct {
	security.Call
	b security.Blessings
}

func (c *mockCall) Server() rpc.Server                   { return nil }
func (c *mockCall) GrantedBlessings() security.Blessings { return c.b }
func (c *mockCall) Security() security.Call              { return c }
func (c *mockCall) LocalBlessings() security.Blessings   { return c.b }
func (c *mockCall) RemoteBlessings() security.Blessings  { return c.b }

func putOp(st store.Store, key, permKey string, permVersion []byte) watchable.OpPut {
	version, _ := watchable.GetVersion(nil, st, []byte(key))
	return watchable.OpPut{watchable.PutOp{
		Key:         []byte(key),
		Version:     version,
		PermKey:     []byte(permKey),
		PermVersion: permVersion,
	}}
}

// TestWatchLogPerms checks that the recorded prefix permissions object
// used to grant access to Put/Delete operations is correct.
func TestWatchLogPerms(t *testing.T) {
	// Prepare V23.
	ctx, shutdown := test.V23Init()
	defer shutdown()
	ctx, _ = v23.WithPrincipal(ctx, testutil.NewPrincipal("root"))
	// Mock the service, store, db, table.
	vClock := clock.NewVClockWithMockServices(memstore.New(), nil, nil)
	st, _ := watchable.Wrap(memstore.New(), vClock, &watchable.Options{
		ManagedPrefixes: []string{util.RowPrefix, util.PermsPrefix},
	})
	db := &databaseReq{database: &database{name: "d", st: st}}
	tb := &tableReq{name: "tb", d: db}
	// Mock create the table.
	perms := access.Permissions{}
	for _, tag := range access.AllTypicalTags() {
		perms.Add(security.BlessingPattern("root"), string(tag))
	}
	util.Put(ctx, st, tb.stKey(), &tableData{
		Name:  tb.name,
		Perms: perms,
	})
	util.Put(ctx, st, tb.prefixPermsKey(""), perms)
	util.Put(ctx, st, tb.permsIndexStart(""), "")
	util.Put(ctx, st, tb.permsIndexLimit(""), "")
	call := &mockCall{b: v23.GetPrincipal(ctx).BlessingStore().Default()}
	var expected []watchable.Op
	resumeMarker, _ := watchable.GetResumeMarker(st)
	// Generate Put/Delete events.
	for i := 0; i < 5; i++ {
		// Set initial prefix permissions.
		if err := tb.SetPrefixPermissions(ctx, call, 0, "foo", perms); err != nil {
			t.Fatalf("tb.SetPrefixPermissions failed: %v", err)
		}
		// Put.
		row := &rowReq{key: "foobar", t: tb}
		if err := row.Put(ctx, call, 0, []byte("value")); err != nil {
			t.Fatalf("row.Put failed: %v", err)
		}
		permVersion, _ := watchable.GetVersion(ctx, st, []byte(tb.prefixPermsKey("foo")))
		expected = append(expected, putOp(st, row.stKey(), tb.prefixPermsKey("foo"), permVersion))
		// Delete.
		if err := row.Delete(ctx, call, 0); err != nil {
			t.Fatalf("row.Delete failed: %v", err)
		}
		deleteOp := watchable.OpDelete{watchable.DeleteOp{
			Key:         []byte(row.stKey()),
			PermKey:     []byte(tb.prefixPermsKey("foo")),
			PermVersion: permVersion,
		}}
		expected = append(expected, deleteOp)
		// DeleteRange.
		if err := row.Put(ctx, call, 0, []byte("value")); err != nil {
			t.Fatalf("row.Put failed: %v", err)
		}
		if err := tb.DeleteRange(ctx, call, 0, []byte("foo"), nil); err != nil {
			t.Fatalf("tb.DeleteRange failed: %v", err)
		}
		expected = append(expected, deleteOp)
		// SetPrefixPermissions.
		if err := tb.SetPrefixPermissions(ctx, call, 0, "foobaz", perms); err != nil {
			t.Fatalf("tb.SetPrefixPermissions failed: %v", err)
		}
		expected = append(expected, putOp(st, tb.prefixPermsKey("foobaz"), tb.prefixPermsKey("foo"), permVersion))
		// SetPrefixPermissions again.
		permVersion, _ = watchable.GetVersion(ctx, st, []byte(tb.prefixPermsKey("foobaz")))
		if err := tb.SetPrefixPermissions(ctx, call, 0, "foobaz", perms); err != nil {
			t.Fatalf("tb.SetPrefixPermissions failed: %v", err)
		}
		expected = append(expected, putOp(st, tb.prefixPermsKey("foobaz"), tb.prefixPermsKey("foobaz"), permVersion))
		// DeletePrefixPermissions.
		permVersion, _ = watchable.GetVersion(ctx, st, []byte(tb.prefixPermsKey("foobaz")))
		if err := tb.DeletePrefixPermissions(ctx, call, 0, "foobaz"); err != nil {
			t.Fatalf("tb.DeletePrefixPermissions failed: %v", err)
		}
		expected = append(expected, watchable.OpDelete{watchable.DeleteOp{
			Key:         []byte(tb.prefixPermsKey("foobaz")),
			PermKey:     []byte(tb.prefixPermsKey("foobaz")),
			PermVersion: permVersion,
		}})
	}
	expectedIndex := 0
	for {
		var logs []*watchable.LogEntry
		if logs, resumeMarker, _ = watchable.ReadBatchFromLog(st, resumeMarker); logs == nil {
			break
		}
		for _, logRecord := range logs {
			if expectedIndex < len(expected) && reflect.DeepEqual(logRecord.Op, expected[expectedIndex]) {
				expectedIndex++
			}
		}
	}
	if expectedIndex != len(expected) {
		t.Fatalf("only %d out of %d record were found", expectedIndex, len(expected))
	}
}
