func main() { // read argument from CLI usage := func() { fmt.Println("ab runs for given amount in time in seconds.") fmt.Println("after it ran for the given amaount of time it reports on the received requests.") fmt.Println("sampe use:") fmt.Println("$ airbiscuit 60") fmt.Println("GET count: 111") fmt.Println("POST count: 122") } if len(os.Args) != 2 { usage() return } wait, err := strconv.Atoi(os.Args[1]) if err != nil { usage() return } // assemble the server s := airbiscuit.NewStats(500 * time.Millisecond) r := airbiscuit.Router(s) srv := graceful.Server{ Timeout: 5 * time.Second, Server: &http.Server{ Handler: r, Addr: ":3001", }, } // stop server after wait time go func() { time.Sleep(time.Duration(wait * int(time.Second))) srv.Stop(100 * time.Millisecond) fmt.Printf("Get count: %d\n", s.G) fmt.Printf("Post count: %d\n", s.P) }() srv.ListenAndServe() }
func TestIntegrationOfHttpPackage(t *testing.T) { if testing.Short() { t.Skip("skipping test in short mode.") } // init gg.Testscenario("scenario1", endurance) // main part err := gg.ReadConfigValidate(airbiscuitLoadmodel, gogrinder.LoadmodelSchema) if err != nil { t.Fatalf("Error while reading loadmodel config: %s!", err.Error()) } // start the airbiscuit server s := &airbiscuit.Stats{Sleep: 50 * time.Millisecond} r := airbiscuit.Router(s) srv := graceful.Server{ Timeout: 50 * time.Millisecond, Server: &http.Server{ Handler: r, Addr: ":3001", }, } // stop server after wait time go func() { time.Sleep(time.Duration(1050 * int(time.Millisecond))) srv.Stop(80 * time.Millisecond) fmt.Printf("Get count: %d\n", s.G) fmt.Printf("Post count: %d\n", s.P) }() go srv.ListenAndServe() // run the test start := time.Now() gg.Exec() // exec the scenario that has been selected in the config file execution := time.Now().Sub(start) // verify total run time of the endurance scenario if execution > 1100*time.Millisecond { t.Errorf("Error: execution time of scenario1 not as expected: %v\n", execution) } results := gg.Results("") // check 01_01_teststep (get requests) if results[0].Teststep != "01_01_teststep" { t.Errorf("Teststep name not as expected: %s!", results[0].Teststep) } if results[0].Count < 170 { t.Errorf("Less than 170 get requests: %v!", results[0].Count) } if results[0].Avg < 50.0 && results[0].Avg > 62.0 { t.Errorf("Average not as expected: %f!", results[0].Avg) } if results[0].Min < 50.0 && results[0].Min > 62.0 { t.Errorf("Minimum not as expected: %f!", results[0].Min) } if results[0].Max < 50.0 && results[0].Max > 62.0 { t.Errorf("Maximum not as expected: %f!", results[0].Max) } // check 02_01_teststep (post requests) if results[1].Teststep != "02_01_teststep" { t.Errorf("Teststep name not as expected: %s!", results[1].Teststep) } if results[1].Count < 170 { t.Errorf("Less than 170 get requests: %v!", results[1].Count) } if results[1].Avg < 50.0 && results[1].Avg > 62.0 { t.Errorf("Average not as expected: %f!", results[1].Avg) } if results[1].Min < 50.0 && results[1].Min > 62.0 { t.Errorf("Minimum not as expected: %f!", results[1].Min) } if results[1].Max < 50.0 && results[1].Max > 62.0 { t.Errorf("Maximum not as expected: %f!", results[1].Max) } }
// This is the "standard" gogrinder behaviour. If you need a special configuration // or setup then maybe you should start with this code. func GoGrinder(test Scenario) error { var err error filename, noExec, noReport, noFrontend, noPrometheus, jtl, port, logLevel, err := GetCLI() if err != nil { return err } ll, _ := log.ParseLevel(logLevel) log.SetLevel(ll) err = test.ReadConfig(filename) if err != nil { return err } // prepare reporter plugins if jtl { // initialize the jtl reporter fj, err := os.OpenFile("results.jtl", os.O_CREATE|os.O_TRUNC|os.O_WRONLY, 0666) if err != nil { log.Error("can not open jtl file: %v", err) // we do not need to stop in this case... } defer fj.Close() test.AddReportPlugin(&JtlReporter{fj}) } else { // initialize the event reporter fe, err := os.OpenFile("event-log.txt", os.O_CREATE|os.O_TRUNC|os.O_WRONLY, 0666) if err != nil { log.Error("can not open event log file: %v", err) } defer fe.Close() test.AddReportPlugin(&EventReporter{fe}) } // result reporter exec := func() { err = test.Exec() if !noReport { test.Report(stdout) } } frontend := func() { srv := NewTestServer(test) srv.Addr = fmt.Sprintf(":%d", port) err = srv.ListenAndServe() } // prometheus reporter needs to "wrap" all test executions var srv *graceful.Server if !noPrometheus { srv = NewPrometheusReporterServer() srv.Addr = fmt.Sprintf(":%d", 9110) go srv.ListenAndServe() // if for example the port is in use we continue... } // handle the different run modes // invalid mode of noExec && noFrontend is handled in cli.go if noExec { frontend() } if noFrontend { exec() } if !noExec && !noFrontend { // this is the "normal" case - webserver is blocking go exec() frontend() } // run for another +2 * scrape_interval so we read all metrics in if !noPrometheus { time.Sleep(11 * time.Second) srv.Stop(1 * time.Second) } return err }