예제 #1
0
func TestBasicController(test *testing.T) {
	filePath := "/tmp/test_basic_controller.log"
	simpleLog := log.SimpleFileLog{}
	if err := simpleLog.Initialize(filePath); err != nil {
		test.Fatalf("could not initialize log backend: %v", err)
		return
	}
	logger := simpleLog.NewLogger("test-basic-controller")
	logger.Infof("starting new controller test")

	controller := &BasicController{}
	controller.Initialize(logger)
	defer func() {
		if err := controller.Close(); err != nil {
			test.Errorf("could not close the controller: %v", err)
			return
		}

		lock, errLock := controller.LockAll()
		if !errs.IsClosed(errLock) {
			test.Errorf("controller issued lock %v after it is closed", lock)
			return
		}

		// Lock and Unlock work even after a Close. Safety is not expected.
		foobar := controller.ReadLock("foo", "bar")
		foobar.Unlock()
	}()

	lock1, errLock1 := controller.LockAll()
	if errLock1 != nil {
		test.Errorf("could not acquire lock1: %v", errLock1)
		return
	}

	lock2, errLock2 := controller.TimedLockAll(time.Millisecond)
	if !errs.IsTimeout(errLock2) {
		test.Errorf("second lock %v is issued while lock1 %v is active",
			lock2, lock1)
		return
	}
	lock1.Unlock()

	lock3, errLock3 := controller.TimedLock(time.Millisecond, "a")
	if errLock3 != nil {
		test.Errorf("could not acquire lock3: %v", errLock3)
		return
	}

	lock4, errLock4 := controller.TimedLock(time.Millisecond, "b")
	if errLock4 != nil {
		test.Errorf("could not acquire lock4: %v", errLock4)
		return
	}

	lock5, errLock5 := controller.TimedLockAll(time.Millisecond)
	if errLock5 == nil {
		test.Errorf("lock all lock %v issue while locks %v and %v are active",
			lock5, lock3, lock4)
		return
	}

	lock3.Unlock()
	lock4.Unlock()

	foo := controller.ReadLock("foo")
	bar := controller.ReadLock("bar")
	bar.Unlock("bar")
	foo.Unlock("foo")

	baz := controller.ReadLock("baz")
	baz.Unlock()

	test.Logf("returning")
}
예제 #2
0
func TestCondition(test *testing.T) {
	mutex := sync.Mutex{}
	cond := &Condition{}
	cond.Initialize(&mutex)

	// A signal must wake up waiting condition.
	mutex.Lock()
	go func() {
		mutex.Lock()
		cond.Signal()
		mutex.Unlock()
	}()
	if err := cond.Wait(); err != nil {
		test.Errorf("condition woke up with a non-nil error: %v", err)
		return
	}
	mutex.Unlock()

	// A signal must wake up timed wait.
	mutex.Lock()
	go func() {
		mutex.Lock()
		cond.Signal()
		mutex.Unlock()
	}()
	if err := cond.WaitTimeout(time.After(time.Second)); err != nil {
		test.Errorf("timed wait woke up with a non-nil error on signal: %v", err)
		return
	}
	mutex.Unlock()

	// A broadcast must wake up all waiters.
	wg := sync.WaitGroup{}
	for ii := 0; ii < 10; ii++ {
		doneCh := make(chan bool)
		wg.Add(1)
		go func() {
			mutex.Lock()
			doneCh <- true
			if err := cond.Wait(); err != nil {
				test.Errorf("wait returned with unexpected status: %v", err)
			}
			mutex.Unlock()
			wg.Done()
		}()
		<-doneCh
	}
	mutex.Lock()
	cond.Broadcast()
	mutex.Unlock()
	wg.Wait()

	// A broadcast must wake up all timed waiters.
	for ii := 0; ii < 10; ii++ {
		doneCh := make(chan bool)
		wg.Add(1)
		go func() {
			mutex.Lock()
			doneCh <- true
			if err := cond.WaitTimeout(time.After(time.Minute)); err != nil {
				test.Errorf("timed wait returned with unexpected status: %v", err)
			}
			mutex.Unlock()
			wg.Done()
		}()
		<-doneCh
	}
	mutex.Lock()
	cond.Broadcast()
	mutex.Unlock()
	wg.Wait()

	// A timeout must wake up the condition.
	mutex.Lock()
	if err := cond.WaitTimeout(time.After(time.Second)); !errs.IsTimeout(err) {
		test.Errorf("timed wait woke up with unexpected status: %v", err)
		return
	}
	mutex.Unlock()

	// Closing a condition must wake up all timed waiters and normal waiters.
	for ii := 0; ii < 10; ii++ {
		doneCh := make(chan bool)
		wg.Add(1)
		go func() {
			mutex.Lock()
			doneCh <- true
			if err := cond.Wait(); !errs.IsClosed(err) {
				test.Errorf("wait returned with unexpected status: %v", err)
			}
			mutex.Unlock()
			wg.Done()
		}()
		<-doneCh
	}
	for ii := 0; ii < 10; ii++ {
		doneCh := make(chan bool)
		wg.Add(1)
		go func() {
			mutex.Lock()
			doneCh <- true
			errWait := cond.WaitTimeout(time.After(time.Minute))
			if !errs.IsClosed(errWait) {
				test.Errorf("timed wait returned with unexpected status: %v", errWait)
			}
			mutex.Unlock()
			wg.Done()
		}()
		<-doneCh
	}
	cond.Close()
	wg.Wait()
}
예제 #3
0
func TestResourceController(test *testing.T) {
	filePath := "/tmp/test_resource_controller.log"
	simpleLog := log.SimpleFileLog{}
	if err := simpleLog.Initialize(filePath); err != nil {
		test.Fatalf("could not initialize log backend: %v", err)
		return
	}
	logger := simpleLog.NewLogger("test-resource-controller")
	logger.Infof("starting new test")

	controller := &ResourceController{}
	controller.Initialize(logger)

	foo := controller.LockResources("foo")
	bar := controller.LockResources("bar")

	timeoutCh := time.After(time.Millisecond)
	if _, err := controller.TimeLockResources(timeoutCh, "foo"); err == nil {
		test.Errorf("resource foo is issued multiple times")
		return
	}

	timeoutCh = time.After(time.Millisecond)
	if _, err := controller.TimeLockAll(timeoutCh); err == nil {
		test.Errorf("lock all issued when foo and bar are busy")
		return
	}

	bar.Unlock("bar")
	foo.Unlock("foo")

	all := controller.LockAll()
	all.Unlock()

	baz := controller.LockResources("baz")
	baz.Unlock()

	baz2 := controller.LockResources("baz")
	baz2.Unlock()

	// Allow multiple readers on a resource.

	a1 := controller.LockResources("", "aa")
	a2 := controller.LockResources("", "aa")

	timeoutCh = time.After(time.Millisecond)
	if _, err := controller.TimeLockAll(timeoutCh); err == nil {
		test.Errorf("lock all issued when two readers are sharing aa")
		return
	}
	timeoutCh = time.After(time.Millisecond)
	if _, err := controller.TimeLockResources(timeoutCh, "aa"); err == nil {
		test.Errorf("exclusive lock is issued when two readers have aa")
		return
	}
	a1.Unlock()
	a2.Unlock()

	// A close on the timeout channel must unlock the waiters.

	b1 := controller.LockAll()
	timeoutCh2 := make(chan time.Time)
	close(timeoutCh2)
	if _, err := controller.TimeLockAll(timeoutCh2); !errs.IsTimeout(err) {
		test.Errorf("closing timeout channel did not unblock the lock")
		return
	}
	b1.Unlock()
}