// report validates the report arguments, sets up the required resources // and writes the report func report(opts *reportOpts) error { rep, ok := reporters[opts.reporter] if !ok { log.Println("Reporter provided is not supported. Using text") rep = stress.ReportText } var all stress.Results for _, input := range strings.Split(opts.inputf, ",") { in, err := file(input, false) if err != nil { return err } var results stress.Results if err = results.Decode(in); err != nil { return err } in.Close() all = append(all, results...) } all.Sort() out, err := file(opts.outputf, true) if err != nil { return err } defer out.Close() data, err := rep(all) if err != nil { return err } _, err = out.Write(data) return err }
// attack validates the attack arguments, sets up the // required resources, launches the attack and writes the results func attack(opts *attackOpts) error { if opts.rate == 0 && opts.concurrency == 0 { return fmt.Errorf(errRatePrefix + "or " + errConcurrencyPrefix + "can't be zero") } else if opts.rate != 0 && opts.concurrency != 0 { return fmt.Errorf(errRatePrefix + "is conflict with " + errConcurrencyPrefix) } if opts.rate != 0 && opts.duration == 0 { return fmt.Errorf(errDurationPrefix + "can't be zero") } if opts.concurrency != 0 && opts.number == 0 { return fmt.Errorf(errNumberPrefix + "can't be zero") } in, err := file(opts.targetsf, false) if err != nil { return fmt.Errorf(errTargetsFilePrefix+"(%s): %s", opts.targetsf, err) } defer in.Close() var body []byte if opts.bodyf != "" { bodyr, err := file(opts.bodyf, false) if err != nil { return fmt.Errorf(errBodyFilePrefix+"(%s): %s", opts.bodyf, err) } defer bodyr.Close() if body, err = ioutil.ReadAll(bodyr); err != nil { return fmt.Errorf(errBodyFilePrefix+"(%s): %s", opts.bodyf, err) } } targets, err := stress.NewTargetsFrom(in, body, opts.headers.Header) if err != nil { return fmt.Errorf(errTargetsFilePrefix+"(%s): %s", opts.targetsf, err) } if len(targets) == 0 { return fmt.Errorf(errTargetsFilePrefix + " : is empty") } switch opts.ordering { case "random": targets.Shuffle(time.Now().UnixNano()) case "sequential": break default: return fmt.Errorf(errOrderingPrefix+"`%s` is invalid", opts.ordering) } out, err := file(opts.outputf, true) if err != nil { return fmt.Errorf(errOutputFilePrefix+"(%s): %s", opts.outputf, err) } defer out.Close() attacker := stress.NewAttacker(opts.redirects, opts.timeout, *opts.laddr.IPAddr) var results stress.Results if opts.rate != 0 { log.Printf( "Stress is attacking %d targets in %s order and %d rate for %s...\n", len(targets), opts.ordering, opts.rate, opts.duration, ) results = attacker.AttackRate(targets, opts.rate, opts.duration) } else if opts.concurrency != 0 { concurrency := opts.concurrency if opts.concurrency > opts.number { concurrency = opts.number } log.Printf( "Stress is attacking %d targets in %s order and %d concurrency level for %d times...\n", len(targets), opts.ordering, concurrency, opts.number, ) results = attacker.AttackConcy(targets, opts.concurrency, opts.number) } log.Printf("Done! Writing results to '%s'...", opts.outputf) err = results.Encode(out) if err != nil { return err } data, err := stress.ReportText(results) if err != nil { return err } _, err = os.Stdout.Write(data) return err }