// 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"
	"testing"
	"time"

	"v.io/v23/security"
)

// manualTrigger provides a gc trigger that can be signaled manually
type manualTrigger struct {
	gcHasRun bool
	ch       chan time.Time
	nextCh   chan bool
}

func newManualTrigger() *manualTrigger {
	return &manualTrigger{
		ch:     make(chan time.Time),
		nextCh: make(chan bool),
	}
}

// manualTrigger is the trigger that should be provided in GC policy config.
// It returns a chan time.Time that resolves immediately after next is called.
func (mt *manualTrigger) waitForNextGc() <-chan time.Time {
	if !mt.gcHasRun {
		mt.gcHasRun = true
	} else {
		mt.nextCh <- true
	}
	return mt.ch
}

// next should be called to trigger the next policy trigger event.
func (mt *manualTrigger) next() {
	mt.ch <- time.Time{}
	<-mt.nextCh
}

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

	countTriggers := 0
	go func() {
		for i := 0; 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, 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")
	}
}
