func TestRedisPrimitives(t *testing.T) {
	testutils.SkipIfShort(t)

	rp := NewRedisPool(REDIS_SERVER_ADDRESS, REDIS_DB_PRIMITIVE_TESTS)
	assert.Nil(t, rp.FlushDB())

	// create a worker queue for a given type
	codec := StringCodec{}
	qRet, err := NewReadThroughCache(rp, Q_NAME_PRIMITIVES, nil, codec, runtime.NumCPU()-2)
	assert.Nil(t, err)

	// Cast to WorkerQueue since we are testing internals.
	q := qRet.(*RedisRTC)

	inProgress, err := q.inProgress()
	assert.Nil(t, err)
	assert.Equal(t, 0, len(inProgress))

	ID_1, ID_2, ID_3, ID_4, ID_5 := "id_1", "id_2", "id_3", "id_4", "id_5"
	p1 := rtcache.PriorityTimeCombined(3)
	found, err := q.enqueue(ID_1, p1)
	assert.Nil(t, err)
	assert.False(t, found)
	time.Sleep(time.Millisecond * 1)

	found, err = q.enqueue(ID_2, rtcache.PriorityTimeCombined(1))
	assert.Nil(t, err)
	assert.False(t, found)
	time.Sleep(time.Millisecond * 1)

	p3 := rtcache.PriorityTimeCombined(1)
	found, err = q.enqueue(ID_3, p3)
	assert.Nil(t, err)
	assert.False(t, found)
	time.Sleep(time.Millisecond * 1)

	p2 := rtcache.PriorityTimeCombined(0)
	found, err = q.enqueue(ID_2, p2)
	assert.Nil(t, err)
	assert.False(t, found)

	dequedItem, itemsLeft, err := q.dequeue()
	assert.Nil(t, err)
	assert.Equal(t, &workerTask{"id_2", p2}, dequedItem)
	assert.Equal(t, 2, itemsLeft)

	dequedItem, itemsLeft, err = q.dequeue()
	assert.Nil(t, err)
	assert.Equal(t, &workerTask{"id_3", p3}, dequedItem)
	assert.Equal(t, 1, itemsLeft)

	dequedItem, itemsLeft, err = q.dequeue()
	assert.Nil(t, err)
	assert.Equal(t, &workerTask{"id_1", p1}, dequedItem)
	assert.Equal(t, 0, itemsLeft)

	dequedItem, itemsLeft, err = q.dequeue()
	assert.Nil(t, err)
	assert.Nil(t, dequedItem)
	assert.Equal(t, 0, itemsLeft)

	inProgress, err = q.inProgress()
	assert.Nil(t, err)
	sort.Strings(inProgress)
	assert.Equal(t, []string{"id_1", "id_2", "id_3"}, inProgress)

	found, err = q.enqueue(ID_4, 1)
	assert.Nil(t, err)
	assert.False(t, found)
	time.Sleep(time.Millisecond * 5)

	found, err = q.enqueue(ID_5, 1)
	assert.Nil(t, err)
	assert.False(t, found)

	inQueue, err := q.inQueue(100)
	assert.Nil(t, err)
	assert.Equal(t, []string{ID_4, ID_5}, inQueue)
	time.Sleep(time.Millisecond * 5)

	found, err = q.enqueue(ID_5, 0)
	assert.Nil(t, err)
	assert.False(t, found)

	inQueue, err = q.inQueue(100)
	assert.Nil(t, err)
	assert.Equal(t, []string{ID_5, ID_4}, inQueue)

	// Test listening to a list.
	const N_MESSAGES = 10000
	const TEST_LIST = "mytestlist"
	assert.Nil(t, rp.FlushDB())

	listCh := rp.List(TEST_LIST)

	go func() {
		for i := 0; i < N_MESSAGES; i++ {
			id := "id-" + strconv.Itoa(i)
			if err := rp.AppendList(TEST_LIST, []byte(id)); err != nil {
				panic(fmt.Sprintf("AddToList failed: %s", err))
			}
		}
	}()

	tick := time.Tick(60 * time.Second)
	for i := 0; i < N_MESSAGES; i++ {
		select {
		case <-listCh:
		case <-tick:
			assert.Fail(t, "Timeout in testing list channel")
		}
	}

	// Test hash save and load
	const TEST_HASH_KEY = "my-test-hash"
	ts1 := testStruct{
		Name:    "myName",
		Content: []byte("my content"),
	}
	var ts2 testStruct

	assert.Nil(t, rp.SaveHash(TEST_HASH_KEY, &ts1))
	foundHash, err := rp.LoadHashToStruct(TEST_HASH_KEY, &ts2)
	assert.Nil(t, err)
	assert.True(t, foundHash)
	assert.Equal(t, ts1, ts2)

	assert.Nil(t, rp.DeleteKey(TEST_HASH_KEY))
	foundHash, err = rp.LoadHashToStruct(TEST_HASH_KEY, &ts2)
	assert.Nil(t, err)
	assert.False(t, foundHash)
}
func TestEventBusGlobally(t *testing.T) {
	testutils.SkipIfShort(t)

	messages := []*testType{
		&testType{0, "message-1"},
		&testType{1, "message-2"},
		&testType{2, "message-3"},
		&testType{3, "message-4"},
	}

	globalEventBus, err := geventbus.NewNSQEventBus(NSQD_ADDR)
	assert.Nil(t, err)

	secondGlobalBus, err := geventbus.NewNSQEventBus(NSQD_ADDR)
	assert.Nil(t, err)

	// Use atomic ints to sync the callback functions.
	firstMap := newAtomicMap()
	firstEventBus := New(globalEventBus)
	firstEventBus.SubscribeAsync(GLOBAL_TOPIC, func(e interface{}) {
		data := e.(*testType)
		if data.ID == SYNC_MSG {
			firstMap.setReady()
			return
		}
		firstMap.Add(data.ID, data)
	})

	secondMap := newAtomicMap()
	errCh := make(chan error, 100)
	assert.Nil(t, secondGlobalBus.SubscribeAsync(GLOBAL_TOPIC, geventbus.JSONCallback(&testType{}, func(data interface{}, err error) {
		if err != nil {
			errCh <- err
			return
		}

		if data.(*testType).ID == SYNC_MSG {
			secondMap.setReady()
			return
		}

		d := data.(*testType)
		secondMap.Add(d.ID, d)
	})))

	for !firstMap.isReady() && !secondMap.isReady() {
		firstEventBus.Publish(GLOBAL_TOPIC, &testType{SYNC_MSG, "ignore"})
	}

	for _, m := range messages {
		firstEventBus.Publish(GLOBAL_TOPIC, m)
	}

	lmsg := len(messages)
	for ((firstMap.Len() < lmsg) || (secondMap.Len() < lmsg)) && (len(errCh) == 0) {
		time.Sleep(time.Millisecond * 10)
	}

	if len(errCh) > 0 {
		close(errCh)
		for err = range errCh {
			fmt.Printf("Error: %s\n", err)
		}
		assert.Fail(t, "Received too many error messages.")
	}
}