Skip to content
quarry Artifact [6f6e1681f7]
Login

Artifact [6f6e1681f7]

Artifact 6f6e1681f778399a4773df4707e6793f18dbdada2b2e101fcce444620ceb8268:


package oltp

import (
	"fmt"
	"path/filepath"
	"sync"
	"testing"
)

// One sequence per repository, apart from the tickets'; the order given
// is the order numbered; a numbered landing keeps its number.
func TestLandingNumbersAreTheirOwnSequence(t *testing.T) {
	d := openTest(t)
	if err := d.TicketNumbersAssign("q", []string{"t1", "t2"}); err != nil {
		t.Fatal(err)
	}
	if err := d.LandingNumbersAssign("q", []string{"aa", "bb"}); err != nil {
		t.Fatal(err)
	}
	if err := d.LandingNumbersAssign("q", []string{"bb", "cc"}); err != nil {
		t.Fatal(err)
	}
	if err := d.LandingNumbersAssign("other", []string{"zz"}); err != nil {
		t.Fatal(err)
	}
	got, err := d.LandingNumbers("q")
	if err != nil {
		t.Fatal(err)
	}
	if got["aa"] != 1 || got["bb"] != 2 || got["cc"] != 3 || len(got) != 3 {
		t.Fatalf("FAIL: %v", got)
	}
	if o, _ := d.LandingNumbers("other"); o["zz"] != 1 {
		t.Fatalf("FAIL: another repository shares the sequence: %v", o)
	}
	if id, ok, _ := d.LandingNumbered("q", 3); !ok || id != "cc" {
		t.Fatalf("FAIL: !3 names %q", id)
	}
	if _, ok, _ := d.LandingNumbered("q", 9); ok {
		t.Fatal("FAIL: an unassigned number names a landing")
	}
	t.Log("ok: 1 2 3 in order beside tickets 1 2, bb kept its number, another repository starts at 1")
}

// Two handles on one database — two nodes on one file — numbering the
// same landings and their own at once: no number twice, no landing twice.
func TestLandingNumbersConcurrentAssignIsUnique(t *testing.T) {
	path := filepath.Join(t.TempDir(), "oltp.db")
	a, err := Open(path)
	if err != nil {
		t.Fatal(err)
	}
	t.Cleanup(func() { a.Close() })
	b, err := Open(path)
	if err != nil {
		t.Fatal(err)
	}
	t.Cleanup(func() { b.Close() })
	var wg sync.WaitGroup
	errs := make(chan error, 40)
	for i := 0; i < 20; i++ {
		for _, db := range []*DB{a, b} {
			wg.Add(1)
			go func(db *DB, i int) {
				defer wg.Done()
				errs <- db.LandingNumbersAssign("q", []string{"shared", fmt.Sprintf("own%d", i)})
			}(db, i)
		}
	}
	wg.Wait()
	close(errs)
	for err := range errs {
		if err != nil {
			t.Fatal(err)
		}
	}
	got, _ := a.LandingNumbers("q")
	if len(got) != 21 {
		t.Fatalf("FAIL: %d landings numbered, want 21: %v", len(got), got)
	}
	seen := map[int]bool{}
	for _, n := range got {
		if seen[n] || n < 1 || n > 21 {
			t.Fatalf("FAIL: numbers are not 1..21 once each: %v", got)
		}
		seen[n] = true
	}
	t.Log("ok: 21 landings, numbers 1..21 once each")
}