| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287 | 
							- /*
 
- Copyright (c) 2014 Ashley Jeffs
 
- Permission is hereby granted, free of charge, to any person obtaining a copy
 
- of this software and associated documentation files (the "Software"), to deal
 
- in the Software without restriction, including without limitation the rights
 
- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 
- copies of the Software, and to permit persons to whom the Software is
 
- furnished to do so, subject to the following conditions:
 
- The above copyright notice and this permission notice shall be included in
 
- all copies or substantial portions of the Software.
 
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 
- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 
- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 
- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 
- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 
- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 
- THE SOFTWARE.
 
- */
 
- package tunny
 
- import (
 
- 	"sync"
 
- 	"testing"
 
- 	"time"
 
- )
 
- /*--------------------------------------------------------------------------------------------------
 
-  */
 
- func TestBasicJob(t *testing.T) {
 
- 	pool, err := CreatePool(1, func(in interface{}) interface{} {
 
- 		intVal := in.(int)
 
- 		return intVal * 2
 
- 	}).Open()
 
- 	if err != nil {
 
- 		t.Errorf("Failed to create pool: %v", err)
 
- 		return
 
- 	}
 
- 	defer pool.Close()
 
- 	for i := 0; i < 1; i++ {
 
- 		ret, err := pool.SendWork(10)
 
- 		if err != nil {
 
- 			t.Errorf("Failed to send work: %v", err)
 
- 			return
 
- 		}
 
- 		retInt := ret.(int)
 
- 		if ret != 20 {
 
- 			t.Errorf("Wrong return value: %v != %v", 20, retInt)
 
- 		}
 
- 	}
 
- }
 
- func TestParallelJobs(t *testing.T) {
 
- 	nWorkers := 10
 
- 	jobGroup := sync.WaitGroup{}
 
- 	testGroup := sync.WaitGroup{}
 
- 	pool, err := CreatePool(nWorkers, func(in interface{}) interface{} {
 
- 		jobGroup.Done()
 
- 		jobGroup.Wait()
 
- 		intVal := in.(int)
 
- 		return intVal * 2
 
- 	}).Open()
 
- 	if err != nil {
 
- 		t.Errorf("Failed to create pool: %v", err)
 
- 		return
 
- 	}
 
- 	defer pool.Close()
 
- 	for j := 0; j < 1; j++ {
 
- 		jobGroup.Add(nWorkers)
 
- 		testGroup.Add(nWorkers)
 
- 		for i := 0; i < nWorkers; i++ {
 
- 			go func() {
 
- 				ret, err := pool.SendWork(10)
 
- 				if err != nil {
 
- 					t.Errorf("Failed to send work: %v", err)
 
- 					return
 
- 				}
 
- 				retInt := ret.(int)
 
- 				if ret != 20 {
 
- 					t.Errorf("Wrong return value: %v != %v", 20, retInt)
 
- 				}
 
- 				testGroup.Done()
 
- 			}()
 
- 		}
 
- 		testGroup.Wait()
 
- 	}
 
- }
 
- /*--------------------------------------------------------------------------------------------------
 
-  */
 
- // Basic worker implementation
 
- type dummyWorker struct {
 
- 	ready bool
 
- 	t     *testing.T
 
- }
 
- func (d *dummyWorker) TunnyJob(in interface{}) interface{} {
 
- 	if !d.ready {
 
- 		d.t.Errorf("Job called without polling Ready")
 
- 	}
 
- 	d.ready = false
 
- 	return in
 
- }
 
- func (d *dummyWorker) TunnyReady() bool {
 
- 	d.ready = true
 
- 	return d.ready
 
- }
 
- // Test the pool with a basic worker implementation
 
- func TestDummyWorker(t *testing.T) {
 
- 	pool, err := CreateCustomPool([]Worker{&dummyWorker{t: t}}).Open()
 
- 	if err != nil {
 
- 		t.Errorf("Failed to create pool: %v", err)
 
- 		return
 
- 	}
 
- 	defer pool.Close()
 
- 	for i := 0; i < 100; i++ {
 
- 		if result, err := pool.SendWork(12); err != nil {
 
- 			t.Errorf("Failed to send work: %v", err)
 
- 		} else if resInt, ok := result.(int); !ok || resInt != 12 {
 
- 			t.Errorf("Unexpected result from job: %v != %v", 12, result)
 
- 		}
 
- 	}
 
- }
 
- // Extended worker implementation
 
- type dummyExtWorker struct {
 
- 	dummyWorker
 
- 	initialized bool
 
- }
 
- func (d *dummyExtWorker) TunnyJob(in interface{}) interface{} {
 
- 	if !d.initialized {
 
- 		d.t.Errorf("Job called without calling Initialize")
 
- 	}
 
- 	return d.dummyWorker.TunnyJob(in)
 
- }
 
- func (d *dummyExtWorker) TunnyInitialize() {
 
- 	d.initialized = true
 
- }
 
- func (d *dummyExtWorker) TunnyTerminate() {
 
- 	if !d.initialized {
 
- 		d.t.Errorf("Terminate called without calling Initialize")
 
- 	}
 
- 	d.initialized = false
 
- }
 
- // Test the pool with an extended worker implementation
 
- func TestDummyExtWorker(t *testing.T) {
 
- 	pool, err := CreateCustomPool(
 
- 		[]Worker{
 
- 			&dummyExtWorker{
 
- 				dummyWorker: dummyWorker{t: t},
 
- 			},
 
- 		}).Open()
 
- 	if err != nil {
 
- 		t.Errorf("Failed to create pool: %v", err)
 
- 		return
 
- 	}
 
- 	defer pool.Close()
 
- 	for i := 0; i < 100; i++ {
 
- 		if result, err := pool.SendWork(12); err != nil {
 
- 			t.Errorf("Failed to send work: %v", err)
 
- 		} else if resInt, ok := result.(int); !ok || resInt != 12 {
 
- 			t.Errorf("Unexpected result from job: %v != %v", 12, result)
 
- 		}
 
- 	}
 
- }
 
- // Extended and interruptible worker implementation
 
- type dummyExtIntWorker struct {
 
- 	dummyExtWorker
 
- 	jobLock *sync.Mutex
 
- }
 
- func (d *dummyExtIntWorker) TunnyJob(in interface{}) interface{} {
 
- 	d.jobLock.Lock()
 
- 	d.jobLock.Unlock()
 
- 	return d.dummyExtWorker.TunnyJob(in)
 
- }
 
- func (d *dummyExtIntWorker) TunnyReady() bool {
 
- 	d.jobLock.Lock()
 
- 	return d.dummyExtWorker.TunnyReady()
 
- }
 
- func (d *dummyExtIntWorker) TunnyInterrupt() {
 
- 	d.jobLock.Unlock()
 
- }
 
- // Test the pool with an extended and interruptible worker implementation
 
- func TestDummyExtIntWorker(t *testing.T) {
 
- 	pool, err := CreateCustomPool(
 
- 		[]Worker{
 
- 			&dummyExtIntWorker{
 
- 				dummyExtWorker: dummyExtWorker{
 
- 					dummyWorker: dummyWorker{t: t},
 
- 				},
 
- 				jobLock: &sync.Mutex{},
 
- 			},
 
- 		}).Open()
 
- 	if err != nil {
 
- 		t.Errorf("Failed to create pool: %v", err)
 
- 		return
 
- 	}
 
- 	defer pool.Close()
 
- 	for i := 0; i < 100; i++ {
 
- 		if _, err := pool.SendWorkTimed(1, nil); err == nil {
 
- 			t.Errorf("Expected timeout from dummyExtIntWorker.")
 
- 		}
 
- 	}
 
- }
 
- func TestNumWorkers(t *testing.T) {
 
- 	numWorkers := 10
 
- 	pool, err := CreatePoolGeneric(numWorkers).Open()
 
- 	if err != nil {
 
- 		t.Errorf("Failed to create pool: %v", err)
 
- 		return
 
- 	}
 
- 	defer pool.Close()
 
- 	actual := pool.NumWorkers()
 
- 	if actual != numWorkers {
 
- 		t.Errorf("Expected to get %d workers, but got %d", numWorkers, actual)
 
- 	}
 
- }
 
- var waitHalfSecond = func() {
 
- 	time.Sleep(500 * time.Millisecond)
 
- }
 
- func TestNumPendingReportsAllWorkersWithNoWork(t *testing.T) {
 
- 	numWorkers := 10
 
- 	pool, err := CreatePoolGeneric(numWorkers).Open()
 
- 	if err != nil {
 
- 		t.Errorf("Failed to create pool: %v", err)
 
- 		return
 
- 	}
 
- 	defer pool.Close()
 
- 	actual := pool.NumPendingAsyncJobs()
 
- 	if actual != 0 {
 
- 		t.Errorf("Expected to get 0 pending jobs when pool is quiet, but got %d", actual)
 
- 	}
 
- }
 
- func TestNumPendingReportsNotAllWorkersWhenSomeBusy(t *testing.T) {
 
- 	numWorkers := 10
 
- 	pool, err := CreatePoolGeneric(numWorkers).Open()
 
- 	if err != nil {
 
- 		t.Errorf("Failed to create pool: %v", err)
 
- 		return
 
- 	}
 
- 	defer pool.Close()
 
- 	pool.SendWorkAsync(waitHalfSecond, nil)
 
- 	actual := pool.NumPendingAsyncJobs()
 
- 	expected := int32(1)
 
- 	if actual != expected {
 
- 		t.Errorf("Expected to get %d pending jobs when pool has work, but got %d", expected, actual)
 
- 	}
 
- }
 
- /*--------------------------------------------------------------------------------------------------
 
-  */
 
 
  |