package main

import (
	"sync"
	"testing"
)

func TestPolicyMatrix(t *testing.T) {
	a, d := fixture()
	tests := []struct {
		name   string
		s      Subject
		action string
		doc    Document
		want   bool
	}{
		{"owner-read", a, "read", d, true}, {"owner-edit", a, "edit", d, true}, {"member-delete", a, "delete", d, false}, {"unknown", a, "dance", d, false},
	}
	disabled := a
	disabled.Active = false
	tests = append(tests, struct {
		name   string
		s      Subject
		action string
		doc    Document
		want   bool
	}{"disabled", disabled, "read", d, false})
	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			if got := Permit(tt.s, tt.action, tt.doc); got != tt.want {
				t.Fatalf("got %v", got)
			}
		})
	}
	for _, role := range []string{"member", "admin"} {
		s := a
		s.Role = role
		cross := d
		cross.Tenant = "other"
		for _, action := range []string{"read", "edit", "delete"} {
			if Permit(s, action, cross) {
				t.Fatal("cross-tenant allowed")
			}
		}
	}
	locked := d
	locked.Locked = true
	if Permit(a, "edit", locked) {
		t.Fatal("locked document allowed")
	}
	shared := d
	shared.Owner = "bob"
	shared.ViewerGroup = "design"
	if !Permit(a, "read", shared) || Permit(a, "edit", shared) {
		t.Fatal("share must be read-only")
	}
	a.Groups = map[string]bool{}
	if Permit(a, "read", shared) {
		t.Fatal("revoked group still allowed")
	}
}
func TestChangeOwnershipAtomic(t *testing.T) {
	a, d := fixture()
	st := Store{documents: map[string]Document{d.ID: d}}
	var wg sync.WaitGroup
	out := make(chan bool, 2)
	for range 2 {
		wg.Go(func() { out <- st.ChangeOwner(a, d.ID, "bob") })
	}
	wg.Wait()
	close(out)
	n := 0
	for ok := range out {
		if ok {
			n++
		}
	}
	if n != 1 {
		t.Fatalf("successful changes=%d", n)
	}
}
