func BenchmarkRoundRobinUpdate(b *testing.B) {
	for k := 0.; k <= 10; k++ {
		n := int(math.Pow(2, k))
		b.Run(fmt.Sprintf("update/%d", n), func(b *testing.B) {
			b.ReportAllocs()
			balancer := NewRoundRobinBalancer()
			b.ResetTimer()
			for i := 0; i < b.N; i++ {
				b.StopTimer()
				routes := make([]Route, n)
				for index := 0; index < n; index++ {
					routes[index] = testRoute(IPv4Address(int64(index)))
				}
				b.StartTimer()
				balancer.Update(routes)
			}
		})
	}
}
Processor Speed: 2.8 GHz
Number of Processors: 1
Total Number of Cores: 4
L2 Cache (per Core): 256 KB
L3 Cache: 6 MB
Memory: 16 GB
Version: OS X 10.13.5

BenchmarkRoundRobinUpdate/update/1-8             1000000              1460 ns/op             336 B/op          5 allocs/op
BenchmarkRoundRobinUpdate/update/2-8             1000000              1780 ns/op             416 B/op          8 allocs/op
BenchmarkRoundRobinUpdate/update/4-8             1000000              2268 ns/op             576 B/op         14 allocs/op
BenchmarkRoundRobinUpdate/update/8-8              500000              3352 ns/op             896 B/op         26 allocs/op
BenchmarkRoundRobinUpdate/update/16-8             200000              7246 ns/op            2909 B/op         52 allocs/op
BenchmarkRoundRobinUpdate/update/32-8             100000             11500 ns/op            6148 B/op        102 allocs/op
BenchmarkRoundRobinUpdate/update/64-8             100000             22976 ns/op           13140 B/op        201 allocs/op
BenchmarkRoundRobinUpdate/update/128-8             30000             43134 ns/op           26565 B/op        395 allocs/op
BenchmarkRoundRobinUpdate/update/256-8             20000             82270 ns/op           51227 B/op        780 allocs/op
BenchmarkRoundRobinUpdate/update/512-8             10000            166695 ns/op          102301 B/op       1558 allocs/op
BenchmarkRoundRobinUpdate/update/1024-8             5000            332736 ns/op          204300 B/op       3113 allocs/op
package xresolver
import (
	"errors"
	"fmt"
	"github.com/stretchr/testify/assert"
	"math"
	"strconv"
	"testing"
)
func testRoute(ip string) Route {
	return Route{
		Host:   ip,
		Scheme: "http",
	}
}
func TestRoundRobinOperations(t *testing.T) {
	assert := assert.New(t)
	balancer := NewRoundRobinBalancer()
	expected := testRoute("127.0.0.1")
	records, err := balancer.Get()
	assert.Error(err)
	assert.Empty(records)
	err = balancer.Remove(expected)
	assert.Error(err)
	err = balancer.Add(expected)
	assert.NoError(err)
	err = balancer.Add(expected)
	assert.Error(err)
	records, err = balancer.Get()
	assert.NoError(err)
	assert.Equal(1, len(records))
	assert.Equal(expected, records[0])
	err = balancer.Remove(expected)
	assert.NoError(err)
	records, err = balancer.Get()
	assert.Error(err)
	assert.Empty(records)
	balancer.Update([]Route{
		expected,
		testRoute("127.0.0.1"),
		testRoute("8.8.8.8"),
		testRoute("1.1.1.1"),
		testRoute("127.0.0.1"),
	})
	records, err = balancer.Get()
	assert.NoError(err)
	assert.Equal(3, len(records))
	assert.Equal([]Route{
		expected,
		testRoute("8.8.8.8"),
		testRoute("1.1.1.1"),
	}, records)
}
func TestRoundRobinOrder(t *testing.T) {
	assert := assert.New(t)
	balancer := NewRoundRobinBalancer()
	localAddress := testRoute("127.0.0.1")
	googleAddres := testRoute("8.8.8.8")
	addressOnes := testRoute("1.1.1.1")
	balancer.Add(localAddress)
	balancer.Add(googleAddres)
	balancer.Add(addressOnes)
	records, err := balancer.Get()
	assert.NoError(err)
	assert.Equal([]Route{localAddress, googleAddres, addressOnes}, records, "records are assumed to be the order in which added")
	records, err = balancer.Get()
	assert.NoError(err)
	assert.Equal([]Route{googleAddres, addressOnes, localAddress}, records, "records should rotate on another Get()")
	records, err = balancer.Get()
	assert.NoError(err)
	assert.Equal([]Route{addressOnes, localAddress, googleAddres}, records, "records should rotate on another Get()")
	err = balancer.Remove(googleAddres)
	assert.NoError(err)
	records, err = balancer.Get()
	assert.NoError(err)
	assert.Equal([]Route{localAddress, addressOnes}, records, "records should rotate on another Get()")
}
func BenchmarkRoundRobinAdd(b *testing.B) {
	for k := 0.; k <= 10; k++ {
		n := int(math.Pow(2, k))
		b.Run(fmt.Sprintf("add/%d", n), func(b *testing.B) {
			balancer := NewRoundRobinBalancer()
			b.ReportAllocs()
			b.ResetTimer()
			for i := 0; i < b.N; i++ {
				for index := 0; index < n; index++ {
					balancer.Add(testRoute(IPv4Address(int64(index))))
				}
			}
		})
	}
}
func BenchmarkRoundRobinRemove(b *testing.B) {
	for k := 0.; k <= 10; k++ {
		n := int(math.Pow(2, k))
		b.Run(fmt.Sprintf("remove/%d", n), func(b *testing.B) {
			b.ReportAllocs()
			balancer := NewRoundRobinBalancer()
			b.ResetTimer()
			for i := 0; i < b.N; i++ {
				b.StopTimer()
				records := make([]string, n)
				for index := 0; index < n; index++ {
					ip := IPv4Address(int64(index))
					records[index] = ip
					balancer.Add(testRoute(ip))
				}
				b.StartTimer()
				for index := 0; index < n; index++ {
					err := balancer.Remove(testRoute(records[index]))
					if err != nil {
						panic(err)
					}
				}
			}
		})
	}
}