Example #1
0
func TestRepeatSim(t *testing.T) {
	clk := loadsim.NewSimClock()

	req, err := http.NewRequest("GET", "", nil)
	if err != nil {
		log.Fatal(err)
	}
	agents := []loadsim.Agent{
		&loadsim.RepeatAgent{
			BaseRequest: req,
			Clock:       clk,
		},
	}

	worker := makeSimWorker(clk)

	stop := make(chan struct{})
	resCh := loadsim.Simulate(agents, worker, clk, 10*time.Second)
	go clk.Run(stop)

	results := collectResults(resCh)[""]
	close(stop)

	if err := assertStatus(results, http.StatusOK); err != nil {
		t.Error(err)
	}
	if err := assertWorkDurations(results, 100*time.Millisecond, time.Millisecond); err != nil {
		t.Error(err)
	}

	count := len(results)
	if count < 99 || count > 101 {
		t.Errorf("expected 99-101 requests, got %d", count)
	}
}
Example #2
0
func TestHTTP(t *testing.T) {
	var clk loadsim.WallClock
	server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		time.Sleep(100 * time.Millisecond)
		v := r.FormValue("a")
		switch v {
		case "1":
			w.WriteHeader(1)
		case "2":
			w.WriteHeader(2)
		default:
			t.Fatalf("unexpected or missing value for GET parameter `a`: %q", v)
		}
	}))

	req1, err := http.NewRequest("GET", server.URL+"?a=1", nil)
	if err != nil {
		log.Fatal(err)
	}
	req2, err := http.NewRequest("GET", server.URL+"?a=2", nil)
	if err != nil {
		log.Fatal(err)
	}

	agents := []loadsim.Agent{
		&loadsim.RepeatAgent{
			BaseRequest: req1,
			Clock:       &clk,
			ID:          "repeat",
		},
		&loadsim.IntervalAgent{
			BaseRequest: req2,
			Clock:       &clk,
			Interval:    time.Millisecond * 51,
			ID:          "interval",
		},
	}

	expectations := map[string]struct {
		Code, Count int
	}{
		"repeat":   {1, 3},
		"interval": {2, 6},
	}
	counts := make(map[string]int, len(agents))
	durations := make(map[string][]time.Duration, len(agents))

	worker := &loadsim.HTTPWorker{
		Clock: &clk,
	}

	results := loadsim.Simulate(agents, worker, &clk, 290*time.Millisecond)
	for res := range results {
		id := res.AgentID
		if want, have := expectations[id].Code, res.StatusCode; want != have {
			t.Errorf("%s: expected status %d, got %d", id, want, have)
		}
		counts[id]++
		durations[id] = append(durations[id], res.End.Sub(res.Start))
	}

	for id, have := range counts {
		want := expectations[id].Count

		if have != want {
			t.Errorf("%s: expected %d requests, got %d (%v)", id, want, have, durations[id])
		}
	}
}
Example #3
0
func TestPoolSim(t *testing.T) {
	clk := loadsim.NewSimClock()

	req, err := http.NewRequest("GET", "", nil)
	if err != nil {
		log.Fatal(err)
	}
	agents := []loadsim.Agent{
		&loadsim.RepeatAgent{
			BaseRequest: req,
			Clock:       clk,
			ID:          "repeat1",
		},
		&loadsim.RepeatAgent{
			BaseRequest: req,
			Clock:       clk,
			ID:          "repeat2",
		},
		&loadsim.IntervalAgent{
			BaseRequest: req,
			Clock:       clk,
			Interval:    510 * time.Millisecond,
			ID:          "interval",
		},
	}

	worker := &loadsim.WorkerPool{
		Backlog: 10,
		Timeout: 200 * time.Millisecond,
		Workers: []loadsim.Worker{makeSimWorker(clk), makeSimWorker(clk)},
		Clock:   clk,
	}

	stop := make(chan struct{})
	resCh := loadsim.Simulate(agents, worker, clk, 10*time.Second)
	go clk.Run(stop)

	agentResults := collectResults(resCh)
	close(stop)

	for id, results := range agentResults {
		if err := assertStatus(results, http.StatusOK); err != nil {
			t.Errorf("%s: %s", id, err)
		}
		if err := assertWorkDurations(results, 100*time.Millisecond, time.Millisecond); err != nil {
			t.Errorf("%s: %s", id, err)
		}

		count := len(results)
		switch id {
		case "repeat1", "repeat2":
			if count < 85 || count > 95 {
				t.Errorf("%s: expected 85-95 requests, got %d", id, count)
			}
		case "interval":
			if count != 20 {
				t.Errorf("%s: expected 20 requests, got %d", id, count)
			}
		}
	}
}
Example #4
0
func httpRun(cfg WorkerConfig, agents []loadsim.Agent, clk loadsim.Clock) []loadsim.Result {
	resultCh := loadsim.Simulate(agents, &loadsim.HTTPWorker{
		Clock: clk,
	}, clk, cfg.Duration)
	return collect(resultCh)
}
Example #5
0
func simRun(cfg WorkerConfig, agents []loadsim.Agent, clk loadsim.Clock) []loadsim.Result {
	var workers []loadsim.Worker
	var allResources []loadsim.Resource
	simClk := clk.(*loadsim.SimClock)

	var limiter loadsim.Limiter
	if cfg.WallClockRate > 0 {
		var err error
		limiter, err = loadsim.NewWallClockLimiter(cfg.WallClockBurst, cfg.WallClockRate, clk)
		if err != nil {
			panic(err)
		}
	}

	for host := 0; host < cfg.Hosts; host++ {
		cpu := &loadsim.CPUResource{Count: cfg.CPUs}
		allResources = append(allResources, cpu)

		for proc := 0; proc < cfg.Workers; proc++ {
			time := &loadsim.TimeResource{}
			allResources = append(allResources, time)
			workerResources := []loadsim.Resource{cpu, time}

			var worker loadsim.Worker
			worker = &loadsim.SimWorker{
				ResourceMapper: cfg.ResourceMapper,
				Resources:      workerResources,
				Clock:          clk,
				Limiter:        limiter,
			}

			if len(cfg.RequestOverhead) > 0 {
				worker = &loadsim.WorkerOverhead{
					Worker:    worker,
					Clock:     clk,
					Resources: workerResources,
					Needs:     cfg.RequestOverhead,
				}
			}

			workers = append(workers, worker)
		}
	}
	worker := loadsim.WorkerPool{
		Backlog: cfg.Backlog,
		Timeout: cfg.Timeout,
		Workers: workers,
		Clock:   clk,
	}

	stop := make(chan struct{})

	simClk.Hook = func() {
		for _, res := range allResources {
			res.Reset()
		}
	}

	resultCh := loadsim.Simulate(agents, &worker, clk, cfg.Duration)
	go simClk.Run(stop)

	results := collect(resultCh)
	close(stop)

	return results
}