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

import (
	"crypto/ecdsa"
	"crypto/elliptic"
	"crypto/rand"
	"reflect"
	"sync"
	"testing"
	"time"

	"v.io/v23/security"
)

// manualTrigger provides a gc trigger that can be signaled manually
type manualTrigger struct {
	gcShouldBeNext bool
	lock           sync.Mutex
	cond           *sync.Cond
	gcHasRun       bool
}

func newManualTrigger() *manualTrigger {
	mt := &manualTrigger{
		gcShouldBeNext: true,
	}
	mt.cond = sync.NewCond(&mt.lock)
	return mt
}

// policyTrigger is the trigger that should be provided in GC policy config.
// It waits until it receives a signal and then returns a chan time.Time
// that resolves immediately.
func (mt *manualTrigger) waitForNextGc() <-chan time.Time {
	mt.lock.Lock()
	if !mt.gcHasRun {
		mt.gcHasRun = true
	} else {
		mt.gcShouldBeNext = false // hand off control
		mt.cond.Broadcast()
		for !mt.gcShouldBeNext {
			mt.cond.Wait()
		}
	}
	mt.lock.Unlock()

	trigger := make(chan time.Time, 1)
	trigger <- time.Time{}
	return trigger
}

// next should be called to trigger the next policy trigger event.
func (mt *manualTrigger) next() {
	mt.lock.Lock()
	mt.gcShouldBeNext = true // hand off control
	mt.cond.Broadcast()
	for mt.gcShouldBeNext {
		mt.cond.Wait()
	}
	mt.lock.Unlock()
}

// Test just to confirm it signals in order as expected.
func TestManualTrigger(t *testing.T) {
	mt := newManualTrigger()

	countTriggers := 0
	go func() {
		for i := 1; i <= 100; i++ {
			<-mt.waitForNextGc()
			countTriggers++
		}
	}()

	for i := 1; i <= 99; i++ {
		mt.next()
		if countTriggers != i {
			t.Errorf("Expected %d triggers, got %d", i, countTriggers)
		}
	}
}

func newSigner() security.Signer {
	key, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
	if err != nil {
		panic(err)
	}
	return security.NewInMemoryECDSASigner(key)
}

func TestBlessingsCache(t *testing.T) {
	notificationCh := make(chan []BlessingsCacheMessage, 1)
	notifier := func(msg []BlessingsCacheMessage) {
		notificationCh <- msg
	}

	mt := newManualTrigger()

	// Create a BlessingsCache with a GC policy that we can trigger on demand.
	onDemandGCPolicy := &BlessingsCacheGCPolicy{
		nextTrigger: mt.waitForNextGc,
	}
	bc := NewBlessingsCache(notifier, onDemandGCPolicy)

	// Blessings for the tests.
	p, err := security.CreatePrincipal(newSigner(), nil, nil)
	if err != nil {
		t.Fatal("Failed to create principal: ", err)
	}
	blessA, err := p.BlessSelf("A")
	if err != nil {
		t.Fatal("Failed to bless A: ", err)
	}
	blessB, err := p.BlessSelf("B")
	if err != nil {
		t.Fatal("Failed to bless B: ", err)
	}
	blessC, err := p.BlessSelf("C")
	if err != nil {
		t.Fatal("Failed to bless C: ", err)
	}

	// First do puts and make sure the ids are reasonable.
	idA := bc.Put(blessA)
	expectAddMessage(t, notificationCh, 1, blessA)
	idB := bc.Put(blessB)
	expectAddMessage(t, notificationCh, 2, blessB)
	if idA == idB {
		t.Errorf("A and B unexpectedly had same id: %v", idA)
	}

	idA2 := bc.Put(blessA)
	expectNoMessage(t, notificationCh)
	if idA2 != idA {
		t.Errorf("A and A2 expected to have same id, but they were %v and %v",
			idA, idA2)
	}

	// Now perform GC. Check that the values are still in the cache.
	mt.next()
	expectNoMessage(t, notificationCh)

	idGc1A := bc.Put(blessA)
	idGc1B := bc.Put(blessB)
	expectNoMessage(t, notificationCh)
	if idA != idGc1A {
		t.Errorf("Expected to get same id after one gc of A, but got %v and %v",
			idA, idGc1A)
	}
	if idB != idGc1B {
		t.Errorf("Expected to get same id after one gc of B, but got %v and %v",
			idB, idGc1B)
	}

	// Now perform GC to clear the dirty bits.
	mt.next()
	expectNoMessage(t, notificationCh)

	// Update B and add C.
	idGc2B := bc.Put(blessB)
	expectNoMessage(t, notificationCh)
	if idB != idGc2B {
		t.Errorf("Expected to get same id after two gcs of B, but got %v and %v",
			idB, idGc2B)
	}
	idC := bc.Put(blessC)
	expectAddMessage(t, notificationCh, 3, blessC)
	if idC == idA || idC == idB {
		t.Error("C was unexpectedly the same as A or B")
	}

	// Perform GC. A should be removed but B and C should stay.
	mt.next()
	expectDeleteMessage(t, notificationCh, BlessingsCacheDeleteMessage{CacheId: 1, DeleteAfter: 3})
	if idB != bc.Put(blessB) {
		t.Errorf("B seems to have been cleaned up as it was given a new id")
	}
	if idC != bc.Put(blessC) {
		t.Errorf("C seems to have been cleaned up as it was given a new id")
	}
	expectNoMessage(t, notificationCh)

	// Perform GC twice to remove the other items.
	mt.next()
	expectNoMessage(t, notificationCh)
	mt.next()
	expectDeleteMessage(t, notificationCh,
		BlessingsCacheDeleteMessage{CacheId: 2, DeleteAfter: 4},
		BlessingsCacheDeleteMessage{CacheId: 3, DeleteAfter: 2})

	// No notifications should occur on further GCs.
	mt.next()
	mt.next()
	mt.next()
	// Note that this should only be reached after the second GC is done because
	// the GC trigger channel has size 1.
	expectNoMessage(t, notificationCh)

	bc.Stop()
}

func expectNoMessage(t *testing.T, notificationCh chan []BlessingsCacheMessage) {
	select {
	case <-notificationCh:
		t.Errorf("Got message when none expected")
	default:
	}
}

func expectAddMessage(t *testing.T, notificationCh chan []BlessingsCacheMessage, id BlessingsId, bless security.Blessings) {
	select {
	case notifications := <-notificationCh:
		if len(notifications) != 1 {
			t.Fatalf("Got invalid add message with %d messages", len(notifications))
		}
		addMsg := notifications[0].(BlessingsCacheMessageAdd).Value
		if got, want := addMsg.CacheId, id; got != want {
			t.Errorf("Unexpected id in add message: %v. Wanted: %v", got, want)
		}
		if got, want := addMsg.Blessings, bless; !reflect.DeepEqual(got, want) {
			t.Errorf("Blessings unexpectedly not equal. Got %v, want %v", got, want)
		}
	case <-time.After(10 * time.Second):
		t.Fatalf("Timed out waiting for notification")
	}
}

func expectDeleteMessage(t *testing.T, notificationCh chan []BlessingsCacheMessage, expected ...BlessingsCacheDeleteMessage) {
	select {
	case notifications := <-notificationCh:
		if len(notifications) != len(expected) {
			t.Fatalf("Got %d notifications but expected %d delete notifications", len(notifications), len(expected))
		}
		for _, notification := range notifications {
			delNotif := notification.(BlessingsCacheMessageDelete).Value
			var foundMatch bool
			for _, expectedNotif := range expected {
				if reflect.DeepEqual(delNotif, expectedNotif) {
					foundMatch = true
				}
			}
			if !foundMatch {
				t.Errorf("Unexpected delete notification: %v", delNotif)
			}
		}
	case <-time.After(10 * time.Second):
		t.Fatalf("Timed out waiting for notification")
	}
}
