package conf

import (
	"sync"
	"testing"
)

func TestRuntimeSnapshotsAreImmutable(t *testing.T) {
	runtime := NewRuntime(&Data{Database: &Data_Database{Name: "first"}}, &AdminBackend{RouterPrefix: "/api", Jwt: &AdminBackend_JWT{SigningKey: "secret"}})
	admin := runtime.Admin()
	admin.RouterPrefix = "/changed"
	admin.Jwt.SigningKey = "changed"
	data := runtime.Data()
	data.Database.Name = "changed"

	if got := runtime.Admin(); got.RouterPrefix != "/api" || got.Jwt.SigningKey != "secret" {
		t.Fatalf("admin snapshot mutated: %+v", got)
	}
	if got := runtime.Data().Database.Name; got != "first" {
		t.Fatalf("data snapshot mutated: %s", got)
	}
}

func TestRuntimeConcurrentReplaceAndRead(t *testing.T) {
	runtime := NewRuntime(&Data{Database: &Data_Database{Name: "initial"}}, &AdminBackend{Jwt: &AdminBackend_JWT{SigningKey: "initial"}})
	var wait sync.WaitGroup
	for worker := 0; worker < 8; worker++ {
		wait.Add(1)
		go func() {
			defer wait.Done()
			for index := 0; index < 500; index++ {
				_ = runtime.Admin().Jwt.SigningKey
				_ = runtime.Data().Database.Name
			}
		}()
	}
	for index := 0; index < 500; index++ {
		runtime.Replace(&Data{Database: &Data_Database{Name: "next"}}, &AdminBackend{Jwt: &AdminBackend_JWT{SigningKey: "next"}})
	}
	wait.Wait()
}
