package idUtil

import (
	"testing"
)

func TestNewTimeIdentifierSeedGenerator(t *testing.T) {
	generator, err := NewTimeIdentifierSeedGenerator(40, 1, 7, 20)
	if err == nil {
		t.Errorf("there should be err, but now not.")
	}

	generator, err = NewTimeIdentifierSeedGenerator(10, int64(1), 7, 20)
	if err != nil {
		t.Errorf("there should be no err, but now there is.")
	}
	_, err = generator.GenerateNewId()
	if err == nil {
		t.Errorf("there should be err, but now not.")
	}

	generator, err = NewTimeIdentifierSeedGenerator(40, int64(127), 3, 20)
	if err == nil {
		t.Errorf("there should be err, but now not.")
	}

	count := 1048575
	idMap := make(map[int64]struct{}, count)
	for identifier := 0; identifier < 8; identifier++ {
		generator, err = NewTimeIdentifierSeedGenerator(40, int64(identifier), 3, 20)
		if err != nil {
			t.Errorf("There should be no error, but now there is:%s", err)
			return
		}

		for i := 0; i < count; i++ {
			id, err := generator.GenerateNewId()
			if err != nil {
				t.Errorf("There should be no error, but now there is:%s", err)
				return
			}

			if _, exist := idMap[id]; exist {
				t.Errorf("Id:%d is duplicated.", id)
				return
			}

			idMap[id] = struct{}{}
		}
	}
}

func TestNewIdentifierTimeSeedGenerator(t *testing.T) {
	generator, err := NewIdentifierTimeSeedGenerator(int64(1), 7, 40, 20)
	if err == nil {
		t.Errorf("there should be err, but now not.")
	}

	generator, err = NewIdentifierTimeSeedGenerator(int64(1), 7, 10, 20)
	if err != nil {
		t.Errorf("there should be no err, but now there is.")
	}
	_, err = generator.GenerateNewId()
	if err == nil {
		t.Errorf("there should be err, but now not.")
	}

	generator, err = NewIdentifierTimeSeedGenerator(int64(127), 3, 40, 20)
	if err == nil {
		t.Errorf("there should be err, but now not.")
	}

	count := 1048575
	idMap := make(map[int64]struct{}, count)
	for identifier := 0; identifier < 8; identifier++ {
		generator, err = NewIdentifierTimeSeedGenerator(int64(identifier), 3, 40, 20)
		if err != nil {
			t.Errorf("There should be no error, but now there is:%s", err)
			return
		}

		for i := 0; i < count; i++ {
			id, err := generator.GenerateNewId()
			if err != nil {
				t.Errorf("There should be no error, but now there is:%s", err)
				return
			}

			if _, exist := idMap[id]; exist {
				t.Errorf("Id:%d is duplicated.", id)
				return
			}

			idMap[id] = struct{}{}
		}
	}
}

func TestNewIdentifierConstructCountSeedGenerator(t *testing.T) {
	generator, err := NewIdentifierConstructCountSeedGenerator(int64(1), 27, int64(1), 20, 23)
	if err == nil {
		t.Errorf("there should be err, but now not.")
	}

	generator, err = NewIdentifierConstructCountSeedGenerator(int64(32768), 15, int64(1), 18, 30)
	if err == nil {
		t.Errorf("there should be err, but now not.")
	}

	count := 1048575
	idMap := make(map[int64]struct{}, count)
	for identifier := 0; identifier < 8; identifier++ {
		for constructCount := 0; constructCount < 5; constructCount++ {
			generator, err = NewIdentifierConstructCountSeedGenerator(int64(identifier), 15, int64(constructCount), 18, 30)
			if err != nil {
				t.Errorf("There should be no error, but now there is:%s", err)
				return
			}

			for i := 0; i < count; i++ {
				id, err := generator.GenerateNewId()
				if err != nil {
					t.Errorf("There should be no error, but now there is:%s", err)
					return
				}

				if _, exist := idMap[id]; exist {
					t.Errorf("Id:%d is duplicated.", id)
					return
				}

				idMap[id] = struct{}{}
			}
		}
	}
}
