How to use getSimpleRunner method of js Package

Best K6 code snippet using js.getSimpleRunner

runner_test.go

Source:runner_test.go Github

copy

Full Screen

...53 null "gopkg.in/guregu/null.v3"54)55func TestRunnerNew(t *testing.T) {56 t.Run("Valid", func(t *testing.T) {57 r, err := getSimpleRunner("/script.js", `58 let counter = 0;59 export default function() { counter++; }60 `)61 assert.NoError(t, err)62 t.Run("NewVU", func(t *testing.T) {63 vu, err := r.NewVU(make(chan stats.SampleContainer, 100))64 assert.NoError(t, err)65 vuc, ok := vu.(*VU)66 assert.True(t, ok)67 assert.Equal(t, int64(0), vuc.Runtime.Get("counter").Export())68 t.Run("RunOnce", func(t *testing.T) {69 err = vu.RunOnce(context.Background())70 assert.NoError(t, err)71 assert.Equal(t, int64(1), vuc.Runtime.Get("counter").Export())72 })73 })74 })75 t.Run("Invalid", func(t *testing.T) {76 _, err := getSimpleRunner("/script.js", `blarg`)77 assert.EqualError(t, err, "ReferenceError: blarg is not defined at file:///script.js:1:1(0)")78 })79}80func TestRunnerGetDefaultGroup(t *testing.T) {81 r1, err := getSimpleRunner("/script.js", `export default function() {};`)82 if assert.NoError(t, err) {83 assert.NotNil(t, r1.GetDefaultGroup())84 }85 r2, err := NewFromArchive(r1.MakeArchive(), lib.RuntimeOptions{})86 if assert.NoError(t, err) {87 assert.NotNil(t, r2.GetDefaultGroup())88 }89}90func TestRunnerOptions(t *testing.T) {91 r1, err := getSimpleRunner("/script.js", `export default function() {};`)92 if !assert.NoError(t, err) {93 return94 }95 r2, err := NewFromArchive(r1.MakeArchive(), lib.RuntimeOptions{})96 if !assert.NoError(t, err) {97 return98 }99 testdata := map[string]*Runner{"Source": r1, "Archive": r2}100 for name, r := range testdata {101 t.Run(name, func(t *testing.T) {102 assert.Equal(t, r.Bundle.Options, r.GetOptions())103 assert.Equal(t, null.NewBool(false, false), r.Bundle.Options.Paused)104 r.SetOptions(lib.Options{Paused: null.BoolFrom(true)})105 assert.Equal(t, r.Bundle.Options, r.GetOptions())106 assert.Equal(t, null.NewBool(true, true), r.Bundle.Options.Paused)107 r.SetOptions(lib.Options{Paused: null.BoolFrom(false)})108 assert.Equal(t, r.Bundle.Options, r.GetOptions())109 assert.Equal(t, null.NewBool(false, true), r.Bundle.Options.Paused)110 })111 }112}113func TestOptionsSettingToScript(t *testing.T) {114 t.Parallel()115 optionVariants := []string{116 "",117 "let options = null;",118 "let options = undefined;",119 "let options = {};",120 "let options = {teardownTimeout: '1s'};",121 }122 for i, variant := range optionVariants {123 variant := variant124 t.Run(fmt.Sprintf("Variant#%d", i), func(t *testing.T) {125 t.Parallel()126 data := variant + `127 export default function() {128 if (!options) {129 throw new Error("Expected options to be defined!");130 }131 if (options.teardownTimeout != __ENV.expectedTeardownTimeout) {132 throw new Error("expected teardownTimeout to be " + __ENV.expectedTeardownTimeout + " but it was " + options.teardownTimeout);133 }134 };`135 r, err := getSimpleRunnerWithOptions("/script.js", data,136 lib.RuntimeOptions{Env: map[string]string{"expectedTeardownTimeout": "4s"}})137 require.NoError(t, err)138 newOptions := lib.Options{TeardownTimeout: types.NullDurationFrom(4 * time.Second)}139 r.SetOptions(newOptions)140 require.Equal(t, newOptions, r.GetOptions())141 samples := make(chan stats.SampleContainer, 100)142 vu, err := r.NewVU(samples)143 if assert.NoError(t, err) {144 err := vu.RunOnce(context.Background())145 assert.NoError(t, err)146 }147 })148 }149}150func TestOptionsPropagationToScript(t *testing.T) {151 t.Parallel()152 data := `153 export let options = { setupTimeout: "1s", myOption: "test" };154 export default function() {155 if (options.external) {156 throw new Error("Unexpected property external!");157 }158 if (options.myOption != "test") {159 throw new Error("expected myOption to remain unchanged but it was '" + options.myOption + "'");160 }161 if (options.setupTimeout != __ENV.expectedSetupTimeout) {162 throw new Error("expected setupTimeout to be " + __ENV.expectedSetupTimeout + " but it was " + options.setupTimeout);163 }164 };`165 expScriptOptions := lib.Options{SetupTimeout: types.NullDurationFrom(1 * time.Second)}166 r1, err := getSimpleRunnerWithOptions("/script.js", data,167 lib.RuntimeOptions{Env: map[string]string{"expectedSetupTimeout": "1s"}})168 require.NoError(t, err)169 require.Equal(t, expScriptOptions, r1.GetOptions())170 r2, err := NewFromArchive(r1.MakeArchive(), lib.RuntimeOptions{Env: map[string]string{"expectedSetupTimeout": "3s"}})171 require.NoError(t, err)172 require.Equal(t, expScriptOptions, r2.GetOptions())173 newOptions := lib.Options{SetupTimeout: types.NullDurationFrom(3 * time.Second)}174 r2.SetOptions(newOptions)175 require.Equal(t, newOptions, r2.GetOptions())176 testdata := map[string]*Runner{"Source": r1, "Archive": r2}177 for name, r := range testdata {178 t.Run(name, func(t *testing.T) {179 samples := make(chan stats.SampleContainer, 100)180 vu, err := r.NewVU(samples)181 if assert.NoError(t, err) {182 err := vu.RunOnce(context.Background())183 assert.NoError(t, err)184 }185 })186 }187}188func TestMetricName(t *testing.T) {189 tb := httpmultibin.NewHTTPMultiBin(t)190 defer tb.Cleanup()191 script := tb.Replacer.Replace(`192 import { Counter } from "k6/metrics";193 let myCounter = new Counter("not ok name @");194 export default function(data) {195 myCounter.add(1);196 }197 `)198 _, err := getSimpleRunner("/script.js", script)199 require.Error(t, err)200}201func TestSetupDataIsolation(t *testing.T) {202 tb := httpmultibin.NewHTTPMultiBin(t)203 defer tb.Cleanup()204 script := tb.Replacer.Replace(`205 import { Counter } from "k6/metrics";206 export let options = {207 vus: 2,208 vusMax: 10,209 iterations: 500,210 teardownTimeout: "1s",211 setupTimeout: "1s",212 };213 let myCounter = new Counter("mycounter");214 export function setup() {215 return { v: 0 };216 }217 export default function(data) {218 if (data.v !== __ITER) {219 throw new Error("default: wrong data for iter " + __ITER + ": " + JSON.stringify(data));220 }221 data.v += 1;222 myCounter.add(1);223 }224 export function teardown(data) {225 if (data.v !== 0) {226 throw new Error("teardown: wrong data: " + data.v);227 }228 myCounter.add(1);229 }230 `)231 runner, err := getSimpleRunner("/script.js", script)232 require.NoError(t, err)233 engine, err := core.NewEngine(local.New(runner), runner.GetOptions())234 require.NoError(t, err)235 collector := &dummy.Collector{}236 engine.Collectors = []lib.Collector{collector}237 ctx, cancel := context.WithCancel(context.Background())238 errC := make(chan error)239 go func() { errC <- engine.Run(ctx) }()240 select {241 case <-time.After(10 * time.Second):242 cancel()243 t.Fatal("Test timed out")244 case err := <-errC:245 cancel()246 require.NoError(t, err)247 require.False(t, engine.IsTainted())248 }249 var count int250 for _, s := range collector.Samples {251 if s.Metric.Name == "mycounter" {252 count += int(s.Value)253 }254 }255 require.Equal(t, 501, count, "mycounter should be the number of iterations + 1 for the teardown")256}257func testSetupDataHelper(t *testing.T, data string) {258 t.Helper()259 expScriptOptions := lib.Options{260 SetupTimeout: types.NullDurationFrom(1 * time.Second),261 TeardownTimeout: types.NullDurationFrom(1 * time.Second),262 }263 r1, err := getSimpleRunner("/script.js", data) // TODO fix this264 require.NoError(t, err)265 require.Equal(t, expScriptOptions, r1.GetOptions())266 testdata := map[string]*Runner{"Source": r1}267 for name, r := range testdata {268 t.Run(name, func(t *testing.T) {269 samples := make(chan stats.SampleContainer, 100)270 if !assert.NoError(t, r.Setup(context.Background(), samples)) {271 return272 }273 vu, err := r.NewVU(samples)274 if assert.NoError(t, err) {275 err := vu.RunOnce(context.Background())276 assert.NoError(t, err)277 }278 })279 }280}281func TestSetupDataReturnValue(t *testing.T) {282 testSetupDataHelper(t, `283 export let options = { setupTimeout: "1s", teardownTimeout: "1s" };284 export function setup() {285 return 42;286 }287 export default function(data) {288 if (data != 42) {289 throw new Error("default: wrong data: " + JSON.stringify(data))290 }291 };292 export function teardown(data) {293 if (data != 42) {294 throw new Error("teardown: wrong data: " + JSON.stringify(data))295 }296 };`)297}298func TestSetupDataNoSetup(t *testing.T) {299 testSetupDataHelper(t, `300 export let options = { setupTimeout: "1s", teardownTimeout: "1s" };301 export default function(data) {302 if (data !== undefined) {303 throw new Error("default: wrong data: " + JSON.stringify(data))304 }305 };306 export function teardown(data) {307 if (data !== undefined) {308 console.log(data);309 throw new Error("teardown: wrong data: " + JSON.stringify(data))310 }311 };`)312}313func TestConsoleInInitContext(t *testing.T) {314 r1, err := getSimpleRunner("/script.js", `315 console.log("1");316 export default function(data) {317 };318 `)319 require.NoError(t, err)320 testdata := map[string]*Runner{"Source": r1}321 for name, r := range testdata {322 r := r323 t.Run(name, func(t *testing.T) {324 samples := make(chan stats.SampleContainer, 100)325 vu, err := r.NewVU(samples)326 if assert.NoError(t, err) {327 err := vu.RunOnce(context.Background())328 assert.NoError(t, err)329 }330 })331 }332}333func TestSetupDataNoReturn(t *testing.T) {334 testSetupDataHelper(t, `335 export let options = { setupTimeout: "1s", teardownTimeout: "1s" };336 export function setup() { }337 export default function(data) {338 if (data !== undefined) {339 throw new Error("default: wrong data: " + JSON.stringify(data))340 }341 };342 export function teardown(data) {343 if (data !== undefined) {344 throw new Error("teardown: wrong data: " + JSON.stringify(data))345 }346 };`)347}348func TestRunnerIntegrationImports(t *testing.T) {349 t.Run("Modules", func(t *testing.T) {350 modules := []string{351 "k6",352 "k6/http",353 "k6/metrics",354 "k6/html",355 }356 for _, mod := range modules {357 mod := mod358 t.Run(mod, func(t *testing.T) {359 t.Run("Source", func(t *testing.T) {360 _, err := getSimpleRunner("/script.js", fmt.Sprintf(`import "%s"; export default function() {}`, mod))361 assert.NoError(t, err)362 })363 })364 }365 })366 t.Run("Files", func(t *testing.T) {367 fs := afero.NewMemMapFs()368 require.NoError(t, fs.MkdirAll("/path/to", 0755))369 require.NoError(t, afero.WriteFile(fs, "/path/to/lib.js", []byte(`export default "hi!";`), 0644))370 testdata := map[string]struct{ filename, path string }{371 "Absolute": {"/path/script.js", "/path/to/lib.js"},372 "Relative": {"/path/script.js", "./to/lib.js"},373 "Adjacent": {"/path/to/script.js", "./lib.js"},374 "STDIN-Absolute": {"-", "/path/to/lib.js"},375 "STDIN-Relative": {"-", "./path/to/lib.js"},376 }377 for name, data := range testdata {378 name, data := name, data379 t.Run(name, func(t *testing.T) {380 r1, err := getSimpleRunnerWithFileFs(data.filename, fmt.Sprintf(`381 import hi from "%s";382 export default function() {383 if (hi != "hi!") { throw new Error("incorrect value"); }384 }`, data.path), fs)385 require.NoError(t, err)386 r2, err := NewFromArchive(r1.MakeArchive(), lib.RuntimeOptions{})387 require.NoError(t, err)388 testdata := map[string]*Runner{"Source": r1, "Archive": r2}389 for name, r := range testdata {390 r := r391 t.Run(name, func(t *testing.T) {392 vu, err := r.NewVU(make(chan stats.SampleContainer, 100))393 require.NoError(t, err)394 err = vu.RunOnce(context.Background())395 require.NoError(t, err)396 })397 }398 })399 }400 })401}402func TestVURunContext(t *testing.T) {403 r1, err := getSimpleRunner("/script.js", `404 export let options = { vus: 10 };405 export default function() { fn(); }406 `)407 require.NoError(t, err)408 r1.SetOptions(r1.GetOptions().Apply(lib.Options{Throw: null.BoolFrom(true)}))409 r2, err := NewFromArchive(r1.MakeArchive(), lib.RuntimeOptions{})410 if !assert.NoError(t, err) {411 return412 }413 testdata := map[string]*Runner{"Source": r1, "Archive": r2}414 for name, r := range testdata {415 t.Run(name, func(t *testing.T) {416 vu, err := r.newVU(make(chan stats.SampleContainer, 100))417 if !assert.NoError(t, err) {418 return419 }420 fnCalled := false421 vu.Runtime.Set("fn", func() {422 fnCalled = true423 assert.Equal(t, vu.Runtime, common.GetRuntime(*vu.Context), "incorrect runtime in context")424 state := lib.GetState(*vu.Context)425 if assert.NotNil(t, state) {426 assert.Equal(t, null.IntFrom(10), state.Options.VUs)427 assert.Equal(t, null.BoolFrom(true), state.Options.Throw)428 assert.NotNil(t, state.Logger)429 assert.Equal(t, r.GetDefaultGroup(), state.Group)430 assert.Equal(t, vu.Transport, state.Transport)431 }432 })433 err = vu.RunOnce(context.Background())434 assert.NoError(t, err)435 assert.True(t, fnCalled, "fn() not called")436 })437 }438}439func TestVURunInterrupt(t *testing.T) {440 //TODO: figure out why interrupt sometimes fails... data race in goja?441 if isWindows {442 t.Skip()443 }444 r1, err := getSimpleRunner("/script.js", `445 export default function() { while(true) {} }446 `)447 require.NoError(t, err)448 require.NoError(t, r1.SetOptions(lib.Options{Throw: null.BoolFrom(true)}))449 r2, err := NewFromArchive(r1.MakeArchive(), lib.RuntimeOptions{})450 require.NoError(t, err)451 testdata := map[string]*Runner{"Source": r1, "Archive": r2}452 for name, r := range testdata {453 name, r := name, r454 t.Run(name, func(t *testing.T) {455 ctx, cancel := context.WithTimeout(context.Background(), 100*time.Millisecond)456 defer cancel()457 samples := make(chan stats.SampleContainer, 100)458 defer close(samples)459 go func() {460 for range samples {461 }462 }()463 vu, err := r.newVU(samples)464 require.NoError(t, err)465 err = vu.RunOnce(ctx)466 assert.Error(t, err)467 assert.True(t, strings.HasPrefix(err.Error(), "context cancelled at "))468 })469 }470}471func TestVUIntegrationGroups(t *testing.T) {472 r1, err := getSimpleRunner("/script.js", `473 import { group } from "k6";474 export default function() {475 fnOuter();476 group("my group", function() {477 fnInner();478 group("nested group", function() {479 fnNested();480 })481 });482 }483 `)484 require.NoError(t, err)485 r2, err := NewFromArchive(r1.MakeArchive(), lib.RuntimeOptions{})486 require.NoError(t, err)487 testdata := map[string]*Runner{"Source": r1, "Archive": r2}488 for name, r := range testdata {489 r := r490 t.Run(name, func(t *testing.T) {491 vu, err := r.newVU(make(chan stats.SampleContainer, 100))492 if !assert.NoError(t, err) {493 return494 }495 fnOuterCalled := false496 fnInnerCalled := false497 fnNestedCalled := false498 vu.Runtime.Set("fnOuter", func() {499 fnOuterCalled = true500 assert.Equal(t, r.GetDefaultGroup(), lib.GetState(*vu.Context).Group)501 })502 vu.Runtime.Set("fnInner", func() {503 fnInnerCalled = true504 g := lib.GetState(*vu.Context).Group505 assert.Equal(t, "my group", g.Name)506 assert.Equal(t, r.GetDefaultGroup(), g.Parent)507 })508 vu.Runtime.Set("fnNested", func() {509 fnNestedCalled = true510 g := lib.GetState(*vu.Context).Group511 assert.Equal(t, "nested group", g.Name)512 assert.Equal(t, "my group", g.Parent.Name)513 assert.Equal(t, r.GetDefaultGroup(), g.Parent.Parent)514 })515 err = vu.RunOnce(context.Background())516 assert.NoError(t, err)517 assert.True(t, fnOuterCalled, "fnOuter() not called")518 assert.True(t, fnInnerCalled, "fnInner() not called")519 assert.True(t, fnNestedCalled, "fnNested() not called")520 })521 }522}523func TestVUIntegrationMetrics(t *testing.T) {524 r1, err := getSimpleRunner("/script.js", `525 import { group } from "k6";526 import { Trend } from "k6/metrics";527 let myMetric = new Trend("my_metric");528 export default function() { myMetric.add(5); }529 `)530 require.NoError(t, err)531 r2, err := NewFromArchive(r1.MakeArchive(), lib.RuntimeOptions{})532 require.NoError(t, err)533 testdata := map[string]*Runner{"Source": r1, "Archive": r2}534 for name, r := range testdata {535 t.Run(name, func(t *testing.T) {536 samples := make(chan stats.SampleContainer, 100)537 vu, err := r.newVU(samples)538 if !assert.NoError(t, err) {539 return540 }541 err = vu.RunOnce(context.Background())542 assert.NoError(t, err)543 sampleCount := 0544 for i, sampleC := range stats.GetBufferedSamples(samples) {545 for j, s := range sampleC.GetSamples() {546 sampleCount++547 switch i + j {548 case 0:549 assert.Equal(t, 5.0, s.Value)550 assert.Equal(t, "my_metric", s.Metric.Name)551 assert.Equal(t, stats.Trend, s.Metric.Type)552 case 1:553 assert.Equal(t, 0.0, s.Value)554 assert.Equal(t, metrics.DataSent, s.Metric, "`data_sent` sample is before `data_received` and `iteration_duration`")555 case 2:556 assert.Equal(t, 0.0, s.Value)557 assert.Equal(t, metrics.DataReceived, s.Metric, "`data_received` sample is after `data_received`")558 case 3:559 assert.Equal(t, metrics.IterationDuration, s.Metric, "`iteration-duration` sample is after `data_received`")560 case 4:561 assert.Equal(t, metrics.Iterations, s.Metric, "`iterations` sample is after `iteration_duration`")562 assert.Equal(t, float64(1), s.Value)563 }564 }565 }566 assert.Equal(t, sampleCount, 5)567 })568 }569}570func TestVUIntegrationInsecureRequests(t *testing.T) {571 testdata := map[string]struct {572 opts lib.Options573 errMsg string574 }{575 "Null": {576 lib.Options{},577 "GoError: Get https://expired.badssl.com/: x509: certificate has expired or is not yet valid",578 },579 "False": {580 lib.Options{InsecureSkipTLSVerify: null.BoolFrom(false)},581 "GoError: Get https://expired.badssl.com/: x509: certificate has expired or is not yet valid",582 },583 "True": {584 lib.Options{InsecureSkipTLSVerify: null.BoolFrom(true)},585 "",586 },587 }588 for name, data := range testdata {589 t.Run(name, func(t *testing.T) {590 r1, err := getSimpleRunner("/script.js", `591 import http from "k6/http";592 export default function() { http.get("https://expired.badssl.com/"); }593 `)594 require.NoError(t, err)595 r1.SetOptions(lib.Options{Throw: null.BoolFrom(true)}.Apply(data.opts))596 r2, err := NewFromArchive(r1.MakeArchive(), lib.RuntimeOptions{})597 require.NoError(t, err)598 runners := map[string]*Runner{"Source": r1, "Archive": r2}599 for name, r := range runners {600 t.Run(name, func(t *testing.T) {601 r.Logger, _ = logtest.NewNullLogger()602 vu, err := r.NewVU(make(chan stats.SampleContainer, 100))603 if !assert.NoError(t, err) {604 return605 }606 err = vu.RunOnce(context.Background())607 if data.errMsg != "" {608 assert.EqualError(t, err, data.errMsg)609 } else {610 assert.NoError(t, err)611 }612 })613 }614 })615 }616}617func TestVUIntegrationBlacklistOption(t *testing.T) {618 r1, err := getSimpleRunner("/script.js", `619 import http from "k6/http";620 export default function() { http.get("http://10.1.2.3/"); }621 `)622 require.NoError(t, err)623 cidr, err := lib.ParseCIDR("10.0.0.0/8")624 if !assert.NoError(t, err) {625 return626 }627 r1.SetOptions(lib.Options{628 Throw: null.BoolFrom(true),629 BlacklistIPs: []*lib.IPNet{cidr},630 })631 r2, err := NewFromArchive(r1.MakeArchive(), lib.RuntimeOptions{})632 if !assert.NoError(t, err) {633 return634 }635 runners := map[string]*Runner{"Source": r1, "Archive": r2}636 for name, r := range runners {637 t.Run(name, func(t *testing.T) {638 vu, err := r.NewVU(make(chan stats.SampleContainer, 100))639 if !assert.NoError(t, err) {640 return641 }642 err = vu.RunOnce(context.Background())643 assert.EqualError(t, err, "GoError: Get http://10.1.2.3/: IP (10.1.2.3) is in a blacklisted range (10.0.0.0/8)")644 })645 }646}647func TestVUIntegrationBlacklistScript(t *testing.T) {648 r1, err := getSimpleRunner("/script.js", `649 import http from "k6/http";650 export let options = {651 throw: true,652 blacklistIPs: ["10.0.0.0/8"],653 };654 export default function() { http.get("http://10.1.2.3/"); }655 `)656 if !assert.NoError(t, err) {657 return658 }659 r2, err := NewFromArchive(r1.MakeArchive(), lib.RuntimeOptions{})660 if !assert.NoError(t, err) {661 return662 }663 runners := map[string]*Runner{"Source": r1, "Archive": r2}664 for name, r := range runners {665 r := r666 t.Run(name, func(t *testing.T) {667 vu, err := r.NewVU(make(chan stats.SampleContainer, 100))668 if !assert.NoError(t, err) {669 return670 }671 err = vu.RunOnce(context.Background())672 assert.EqualError(t, err, "GoError: Get http://10.1.2.3/: IP (10.1.2.3) is in a blacklisted range (10.0.0.0/8)")673 })674 }675}676func TestVUIntegrationHosts(t *testing.T) {677 tb := httpmultibin.NewHTTPMultiBin(t)678 defer tb.Cleanup()679 r1, err := getSimpleRunner("/script.js",680 tb.Replacer.Replace(`681 import { check, fail } from "k6";682 import http from "k6/http";683 export default function() {684 let res = http.get("http://test.loadimpact.com:HTTPBIN_PORT/");685 check(res, {686 "is correct IP": (r) => r.remote_ip === "127.0.0.1"687 }) || fail("failed to override dns");688 }689 `))690 if !assert.NoError(t, err) {691 return692 }693 r1.SetOptions(lib.Options{694 Throw: null.BoolFrom(true),695 Hosts: map[string]net.IP{696 "test.loadimpact.com": net.ParseIP("127.0.0.1"),697 },698 })699 r2, err := NewFromArchive(r1.MakeArchive(), lib.RuntimeOptions{})700 if !assert.NoError(t, err) {701 return702 }703 runners := map[string]*Runner{"Source": r1, "Archive": r2}704 for name, r := range runners {705 t.Run(name, func(t *testing.T) {706 vu, err := r.NewVU(make(chan stats.SampleContainer, 100))707 if !assert.NoError(t, err) {708 return709 }710 err = vu.RunOnce(context.Background())711 if !assert.NoError(t, err) {712 return713 }714 })715 }716}717func TestVUIntegrationTLSConfig(t *testing.T) {718 var unsupportedVersionErrorMsg = "remote error: tls: handshake failure"719 for _, tag := range build.Default.ReleaseTags {720 if tag == "go1.12" {721 unsupportedVersionErrorMsg = "tls: no supported versions satisfy MinVersion and MaxVersion"722 break723 }724 }725 testdata := map[string]struct {726 opts lib.Options727 errMsg string728 }{729 "NullCipherSuites": {730 lib.Options{},731 "",732 },733 "SupportedCipherSuite": {734 lib.Options{TLSCipherSuites: &lib.TLSCipherSuites{tls.TLS_RSA_WITH_AES_128_GCM_SHA256}},735 "",736 },737 "UnsupportedCipherSuite": {738 lib.Options{TLSCipherSuites: &lib.TLSCipherSuites{tls.TLS_RSA_WITH_RC4_128_SHA}},739 "GoError: Get https://sha256.badssl.com/: remote error: tls: handshake failure",740 },741 "NullVersion": {742 lib.Options{},743 "",744 },745 "SupportedVersion": {746 lib.Options{TLSVersion: &lib.TLSVersions{Min: tls.VersionTLS12, Max: tls.VersionTLS12}},747 "",748 },749 "UnsupportedVersion": {750 lib.Options{TLSVersion: &lib.TLSVersions{Min: tls.VersionSSL30, Max: tls.VersionSSL30}},751 "GoError: Get https://sha256.badssl.com/: " + unsupportedVersionErrorMsg,752 },753 }754 for name, data := range testdata {755 t.Run(name, func(t *testing.T) {756 r1, err := getSimpleRunner("/script.js", `757 import http from "k6/http";758 export default function() { http.get("https://sha256.badssl.com/"); }759 `)760 if !assert.NoError(t, err) {761 return762 }763 r1.SetOptions(lib.Options{Throw: null.BoolFrom(true)}.Apply(data.opts))764 r2, err := NewFromArchive(r1.MakeArchive(), lib.RuntimeOptions{})765 if !assert.NoError(t, err) {766 return767 }768 runners := map[string]*Runner{"Source": r1, "Archive": r2}769 for name, r := range runners {770 t.Run(name, func(t *testing.T) {771 r.Logger, _ = logtest.NewNullLogger()772 vu, err := r.NewVU(make(chan stats.SampleContainer, 100))773 if !assert.NoError(t, err) {774 return775 }776 err = vu.RunOnce(context.Background())777 if data.errMsg != "" {778 assert.EqualError(t, err, data.errMsg)779 } else {780 assert.NoError(t, err)781 }782 })783 }784 })785 }786}787func TestVUIntegrationHTTP2(t *testing.T) {788 r1, err := getSimpleRunner("/script.js", `789 import http from "k6/http";790 export default function() {791 let res = http.request("GET", "https://http2.akamai.com/demo");792 if (res.status != 200) { throw new Error("wrong status: " + res.status) }793 if (res.proto != "HTTP/2.0") { throw new Error("wrong proto: " + res.proto) }794 }795 `)796 if !assert.NoError(t, err) {797 return798 }799 r1.SetOptions(lib.Options{800 Throw: null.BoolFrom(true),801 SystemTags: stats.NewSystemTagSet(stats.TagProto),802 })803 r2, err := NewFromArchive(r1.MakeArchive(), lib.RuntimeOptions{})804 if !assert.NoError(t, err) {805 return806 }807 runners := map[string]*Runner{"Source": r1, "Archive": r2}808 for name, r := range runners {809 t.Run(name, func(t *testing.T) {810 samples := make(chan stats.SampleContainer, 100)811 vu, err := r.NewVU(samples)812 if !assert.NoError(t, err) {813 return814 }815 err = vu.RunOnce(context.Background())816 assert.NoError(t, err)817 protoFound := false818 for _, sampleC := range stats.GetBufferedSamples(samples) {819 for _, sample := range sampleC.GetSamples() {820 if proto, ok := sample.Tags.Get("proto"); ok {821 protoFound = true822 assert.Equal(t, "HTTP/2.0", proto)823 }824 }825 }826 assert.True(t, protoFound)827 })828 }829}830func TestVUIntegrationOpenFunctionError(t *testing.T) {831 r, err := getSimpleRunner("/script.js", `832 export default function() { open("/tmp/foo") }833 `)834 assert.NoError(t, err)835 vu, err := r.NewVU(make(chan stats.SampleContainer, 100))836 assert.NoError(t, err)837 err = vu.RunOnce(context.Background())838 assert.EqualError(t, err, "GoError: \"open\" function is only available to the init code (aka global scope), see https://docs.k6.io/docs/test-life-cycle for more information")839}840func TestVUIntegrationCookiesReset(t *testing.T) {841 tb := httpmultibin.NewHTTPMultiBin(t)842 defer tb.Cleanup()843 r1, err := getSimpleRunner("/script.js", tb.Replacer.Replace(`844 import http from "k6/http";845 export default function() {846 let url = "HTTPBIN_URL";847 let preRes = http.get(url + "/cookies");848 if (preRes.status != 200) { throw new Error("wrong status (pre): " + preRes.status); }849 if (preRes.json().k1 || preRes.json().k2) {850 throw new Error("cookies persisted: " + preRes.body);851 }852 let res = http.get(url + "/cookies/set?k2=v2&k1=v1");853 if (res.status != 200) { throw new Error("wrong status: " + res.status) }854 if (res.json().k1 != "v1" || res.json().k2 != "v2") {855 throw new Error("wrong cookies: " + res.body);856 }857 }858 `))859 if !assert.NoError(t, err) {860 return861 }862 r1.SetOptions(lib.Options{863 Throw: null.BoolFrom(true),864 MaxRedirects: null.IntFrom(10),865 Hosts: tb.Dialer.Hosts,866 })867 r2, err := NewFromArchive(r1.MakeArchive(), lib.RuntimeOptions{})868 if !assert.NoError(t, err) {869 return870 }871 runners := map[string]*Runner{"Source": r1, "Archive": r2}872 for name, r := range runners {873 t.Run(name, func(t *testing.T) {874 vu, err := r.NewVU(make(chan stats.SampleContainer, 100))875 if !assert.NoError(t, err) {876 return877 }878 for i := 0; i < 2; i++ {879 err = vu.RunOnce(context.Background())880 assert.NoError(t, err)881 }882 })883 }884}885func TestVUIntegrationCookiesNoReset(t *testing.T) {886 tb := httpmultibin.NewHTTPMultiBin(t)887 defer tb.Cleanup()888 r1, err := getSimpleRunner("/script.js", tb.Replacer.Replace(`889 import http from "k6/http";890 export default function() {891 let url = "HTTPBIN_URL";892 if (__ITER == 0) {893 let res = http.get(url + "/cookies/set?k2=v2&k1=v1");894 if (res.status != 200) { throw new Error("wrong status: " + res.status) }895 if (res.json().k1 != "v1" || res.json().k2 != "v2") {896 throw new Error("wrong cookies: " + res.body);897 }898 }899 if (__ITER == 1) {900 let res = http.get(url + "/cookies");901 if (res.status != 200) { throw new Error("wrong status (pre): " + res.status); }902 if (res.json().k1 != "v1" || res.json().k2 != "v2") {903 throw new Error("wrong cookies: " + res.body);904 }905 }906 }907 `))908 if !assert.NoError(t, err) {909 return910 }911 r1.SetOptions(lib.Options{912 Throw: null.BoolFrom(true),913 MaxRedirects: null.IntFrom(10),914 Hosts: tb.Dialer.Hosts,915 NoCookiesReset: null.BoolFrom(true),916 })917 r2, err := NewFromArchive(r1.MakeArchive(), lib.RuntimeOptions{})918 if !assert.NoError(t, err) {919 return920 }921 runners := map[string]*Runner{"Source": r1, "Archive": r2}922 for name, r := range runners {923 t.Run(name, func(t *testing.T) {924 vu, err := r.NewVU(make(chan stats.SampleContainer, 100))925 if !assert.NoError(t, err) {926 return927 }928 err = vu.RunOnce(context.Background())929 assert.NoError(t, err)930 err = vu.RunOnce(context.Background())931 assert.NoError(t, err)932 })933 }934}935func TestVUIntegrationVUID(t *testing.T) {936 r1, err := getSimpleRunner("/script.js", `937 export default function() {938 if (__VU != 1234) { throw new Error("wrong __VU: " + __VU); }939 }`,940 )941 if !assert.NoError(t, err) {942 return943 }944 r1.SetOptions(lib.Options{Throw: null.BoolFrom(true)})945 r2, err := NewFromArchive(r1.MakeArchive(), lib.RuntimeOptions{})946 if !assert.NoError(t, err) {947 return948 }949 runners := map[string]*Runner{"Source": r1, "Archive": r2}950 for name, r := range runners {951 t.Run(name, func(t *testing.T) {952 vu, err := r.NewVU(make(chan stats.SampleContainer, 100))953 if !assert.NoError(t, err) {954 return955 }956 assert.NoError(t, vu.Reconfigure(1234))957 err = vu.RunOnce(context.Background())958 assert.NoError(t, err)959 })960 }961}962func TestVUIntegrationClientCerts(t *testing.T) {963 clientCAPool := x509.NewCertPool()964 assert.True(t, clientCAPool.AppendCertsFromPEM(965 []byte("-----BEGIN CERTIFICATE-----\n"+966 "MIIBYzCCAQqgAwIBAgIUMYw1pqZ1XhXdFG0S2ITXhfHBsWgwCgYIKoZIzj0EAwIw\n"+967 "EDEOMAwGA1UEAxMFTXkgQ0EwHhcNMTcwODE1MTYxODAwWhcNMjIwODE0MTYxODAw\n"+968 "WjAQMQ4wDAYDVQQDEwVNeSBDQTBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABFWO\n"+969 "fg4dgL8cdvjoSWDQFLBJxlbQFlZfOSyUR277a4g91BD07KWX+9ny+Q8WuUODog06\n"+970 "xH1g8fc6zuaejllfzM6jQjBAMA4GA1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8EBTAD\n"+971 "AQH/MB0GA1UdDgQWBBTeoSFylGCmyqj1X4sWez1r6hkhjDAKBggqhkjOPQQDAgNH\n"+972 "ADBEAiAfuKi6u/BVXenCkgnU2sfXsYjel6rACuXEcx01yaaWuQIgXAtjrDisdlf4\n"+973 "0ZdoIoYjNhDAXUtnyRBt+V6+rIklv/8=\n"+974 "-----END CERTIFICATE-----"),975 ))976 serverCert, err := tls.X509KeyPair(977 []byte("-----BEGIN CERTIFICATE-----\n"+978 "MIIBxjCCAW2gAwIBAgIUICcYHG1bI28NZm676wHlMPxL+CEwCgYIKoZIzj0EAwIw\n"+979 "EDEOMAwGA1UEAxMFTXkgQ0EwHhcNMTcwODE3MTQwNjAwWhcNMTgwODE3MTQwNjAw\n"+980 "WjAZMRcwFQYDVQQDEw4xMjcuMC4wLjE6Njk2OTBZMBMGByqGSM49AgEGCCqGSM49\n"+981 "AwEHA0IABCdD1IqowucJ5oUjGYCZZnXvgi7EMD4jD1osbOkzOFFnHSLRvdm6fcJu\n"+982 "vPUcl4g8zUs466sC0AVUNpk21XbA/QajgZswgZgwDgYDVR0PAQH/BAQDAgWgMB0G\n"+983 "A1UdJQQWMBQGCCsGAQUFBwMBBggrBgEFBQcDAjAMBgNVHRMBAf8EAjAAMB0GA1Ud\n"+984 "DgQWBBTeAc8HY3sgGIV+fu/lY0OKr2Ho0jAfBgNVHSMEGDAWgBTeoSFylGCmyqj1\n"+985 "X4sWez1r6hkhjDAZBgNVHREEEjAQgg4xMjcuMC4wLjE6Njk2OTAKBggqhkjOPQQD\n"+986 "AgNHADBEAiAt3gC5FGQfSJXQ5DloXAOeJDFnKIL7d6xhftgPS5O08QIgRuAyysB8\n"+987 "5JXHvvze5DMN/clHYptos9idVFc+weUZAUQ=\n"+988 "-----END CERTIFICATE-----\n"+989 "-----BEGIN CERTIFICATE-----\n"+990 "MIIBYzCCAQqgAwIBAgIUMYw1pqZ1XhXdFG0S2ITXhfHBsWgwCgYIKoZIzj0EAwIw\n"+991 "EDEOMAwGA1UEAxMFTXkgQ0EwHhcNMTcwODE1MTYxODAwWhcNMjIwODE0MTYxODAw\n"+992 "WjAQMQ4wDAYDVQQDEwVNeSBDQTBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABFWO\n"+993 "fg4dgL8cdvjoSWDQFLBJxlbQFlZfOSyUR277a4g91BD07KWX+9ny+Q8WuUODog06\n"+994 "xH1g8fc6zuaejllfzM6jQjBAMA4GA1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8EBTAD\n"+995 "AQH/MB0GA1UdDgQWBBTeoSFylGCmyqj1X4sWez1r6hkhjDAKBggqhkjOPQQDAgNH\n"+996 "ADBEAiAfuKi6u/BVXenCkgnU2sfXsYjel6rACuXEcx01yaaWuQIgXAtjrDisdlf4\n"+997 "0ZdoIoYjNhDAXUtnyRBt+V6+rIklv/8=\n"+998 "-----END CERTIFICATE-----"),999 []byte("-----BEGIN EC PRIVATE KEY-----\n"+1000 "MHcCAQEEIKYptA4VtQ8UOKL+d1wkhl+51aPpvO+ppY62nLF9Z1w5oAoGCCqGSM49\n"+1001 "AwEHoUQDQgAEJ0PUiqjC5wnmhSMZgJlmde+CLsQwPiMPWixs6TM4UWcdItG92bp9\n"+1002 "wm689RyXiDzNSzjrqwLQBVQ2mTbVdsD9Bg==\n"+1003 "-----END EC PRIVATE KEY-----"),1004 )1005 if !assert.NoError(t, err) {1006 return1007 }1008 listener, err := tls.Listen("tcp", "127.0.0.1:0", &tls.Config{1009 Certificates: []tls.Certificate{serverCert},1010 ClientAuth: tls.RequireAndVerifyClientCert,1011 ClientCAs: clientCAPool,1012 })1013 if !assert.NoError(t, err) {1014 return1015 }1016 defer func() { _ = listener.Close() }()1017 srv := &http.Server{1018 Handler: http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) {1019 _, _ = fmt.Fprintf(w, "ok")1020 }),1021 ErrorLog: stdlog.New(ioutil.Discard, "", 0),1022 }1023 go func() { _ = srv.Serve(listener) }()1024 r1, err := getSimpleRunner("/script.js", fmt.Sprintf(`1025 import http from "k6/http";1026 export default function() { http.get("https://%s")}1027 `, listener.Addr().String()))1028 if !assert.NoError(t, err) {1029 return1030 }1031 r1.SetOptions(lib.Options{1032 Throw: null.BoolFrom(true),1033 InsecureSkipTLSVerify: null.BoolFrom(true),1034 })1035 t.Run("Unauthenticated", func(t *testing.T) {1036 r2, err := NewFromArchive(r1.MakeArchive(), lib.RuntimeOptions{})1037 if !assert.NoError(t, err) {1038 return1039 }1040 runners := map[string]*Runner{"Source": r1, "Archive": r2}1041 for name, r := range runners {1042 t.Run(name, func(t *testing.T) {1043 r.Logger, _ = logtest.NewNullLogger()1044 vu, err := r.NewVU(make(chan stats.SampleContainer, 100))1045 if assert.NoError(t, err) {1046 err := vu.RunOnce(context.Background())1047 require.NotNil(t, err)1048 assert.Contains(t, err.Error(), "remote error: tls: bad certificate")1049 }1050 })1051 }1052 })1053 r1.SetOptions(lib.Options{1054 TLSAuth: []*lib.TLSAuth{1055 {1056 TLSAuthFields: lib.TLSAuthFields{1057 Domains: []string{"127.0.0.1"},1058 Cert: "-----BEGIN CERTIFICATE-----\n" +1059 "MIIBoTCCAUigAwIBAgIUd6XedDxP+rGo+kq0APqHElGZzs4wCgYIKoZIzj0EAwIw\n" +1060 "EDEOMAwGA1UEAxMFTXkgQ0EwHhcNMTcwODE3MTUwNjAwWhcNMTgwODE3MTUwNjAw\n" +1061 "WjARMQ8wDQYDVQQDEwZjbGllbnQwWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAATL\n" +1062 "mi/a1RVvk05FyrYmartbo/9cW+53DrQLW1twurII2q5ZfimdMX05A32uB3Ycoy/J\n" +1063 "x+w7Ifyd/YRw0zEc3NHQo38wfTAOBgNVHQ8BAf8EBAMCBaAwHQYDVR0lBBYwFAYI\n" +1064 "KwYBBQUHAwEGCCsGAQUFBwMCMAwGA1UdEwEB/wQCMAAwHQYDVR0OBBYEFN2SR/TD\n" +1065 "yNW5DQWxZSkoXHQWsLY+MB8GA1UdIwQYMBaAFN6hIXKUYKbKqPVfixZ7PWvqGSGM\n" +1066 "MAoGCCqGSM49BAMCA0cAMEQCICtETmyOmupmg4w3tw59VYJyOBqRTxg6SK+rOQmq\n" +1067 "kE1VAiAUvsflDfmWBZ8EMPu46OhX6RX6MbvJ9NNvRco2G5ek1w==\n" +1068 "-----END CERTIFICATE-----",1069 Key: "-----BEGIN EC PRIVATE KEY-----\n" +1070 "MHcCAQEEIOrnhT05alCeQEX66HgnSHah/m5LazjJHLDawYRnhUtZoAoGCCqGSM49\n" +1071 "AwEHoUQDQgAEy5ov2tUVb5NORcq2Jmq7W6P/XFvudw60C1tbcLqyCNquWX4pnTF9\n" +1072 "OQN9rgd2HKMvycfsOyH8nf2EcNMxHNzR0A==\n" +1073 "-----END EC PRIVATE KEY-----",1074 },1075 },1076 },1077 })1078 t.Run("Authenticated", func(t *testing.T) {1079 r2, err := NewFromArchive(r1.MakeArchive(), lib.RuntimeOptions{})1080 if !assert.NoError(t, err) {1081 return1082 }1083 runners := map[string]*Runner{"Source": r1, "Archive": r2}1084 for name, r := range runners {1085 t.Run(name, func(t *testing.T) {1086 vu, err := r.NewVU(make(chan stats.SampleContainer, 100))1087 if assert.NoError(t, err) {1088 err := vu.RunOnce(context.Background())1089 assert.NoError(t, err)1090 }1091 })1092 }1093 })1094}1095func TestHTTPRequestInInitContext(t *testing.T) {1096 tb := httpmultibin.NewHTTPMultiBin(t)1097 defer tb.Cleanup()1098 _, err := getSimpleRunner("/script.js", tb.Replacer.Replace(`1099 import { check, fail } from "k6";1100 import http from "k6/http";1101 let res = http.get("HTTPBIN_URL/");1102 export default function() {1103 console.log(test);1104 }1105 `))1106 if assert.Error(t, err) {1107 assert.Equal(1108 t,1109 "GoError: "+k6http.ErrHTTPForbiddenInInitContext.Error(),1110 err.Error())1111 }1112}1113func TestInitContextForbidden(t *testing.T) {1114 var table = [...][3]string{1115 {1116 "http.request",1117 `import http from "k6/http";1118 let res = http.get("HTTPBIN_URL");1119 export default function() { console.log("p"); }`,1120 k6http.ErrHTTPForbiddenInInitContext.Error(),1121 },1122 {1123 "http.batch",1124 `import http from "k6/http";1125 let res = http.batch("HTTPBIN_URL/something", "HTTPBIN_URL/else");1126 export default function() { console.log("p"); }`,1127 k6http.ErrBatchForbiddenInInitContext.Error(),1128 },1129 {1130 "http.cookieJar",1131 `import http from "k6/http";1132 let jar = http.cookieJar();1133 export default function() { console.log("p"); }`,1134 k6http.ErrJarForbiddenInInitContext.Error(),1135 },1136 {1137 "check",1138 `import { check } from "k6";1139 check("test", {'is test': (test) => test == "test"})1140 export default function() { console.log("p"); }`,1141 k6.ErrCheckInInitContext.Error(),1142 },1143 {1144 "group",1145 `import { group } from "k6";1146 group("group1", function () { console.log("group1");})1147 export default function() { console.log("p"); }`,1148 k6.ErrGroupInInitContext.Error(),1149 },1150 {1151 "ws",1152 `import ws from "k6/ws";1153 var url = "ws://echo.websocket.org";1154 var params = { "tags": { "my_tag": "hello" } };1155 var response = ws.connect(url, params, function (socket) {1156 socket.on('open', function open() {1157 console.log('connected');1158 })1159 });1160 export default function() { console.log("p"); }`,1161 ws.ErrWSInInitContext.Error(),1162 },1163 {1164 "metric",1165 `import { Counter } from "k6/metrics";1166 let counter = Counter("myCounter");1167 counter.add(1);1168 export default function() { console.log("p"); }`,1169 k6metrics.ErrMetricsAddInInitContext.Error(),1170 },1171 }1172 tb := httpmultibin.NewHTTPMultiBin(t)1173 defer tb.Cleanup()1174 for _, test := range table {1175 test := test1176 t.Run(test[0], func(t *testing.T) {1177 _, err := getSimpleRunner("/script.js", tb.Replacer.Replace(test[1]))1178 if assert.Error(t, err) {1179 assert.Equal(1180 t,1181 "GoError: "+test[2],1182 err.Error())1183 }1184 })1185 }1186}1187func TestArchiveRunningIntegraty(t *testing.T) {1188 tb := httpmultibin.NewHTTPMultiBin(t)1189 defer tb.Cleanup()1190 fs := afero.NewMemMapFs()1191 data := tb.Replacer.Replace(`1192 let fput = open("/home/somebody/test.json");1193 export let options = { setupTimeout: "10s", teardownTimeout: "10s" };1194 export function setup() {1195 return JSON.parse(fput);1196 }1197 export default function(data) {1198 if (data != 42) {1199 throw new Error("incorrect answer " + data);1200 }1201 }1202 `)1203 require.NoError(t, afero.WriteFile(fs, "/home/somebody/test.json", []byte(`42`), os.ModePerm))1204 require.NoError(t, afero.WriteFile(fs, "/script.js", []byte(data), os.ModePerm))1205 r1, err := getSimpleRunnerWithFileFs("/script.js", data, fs)1206 require.NoError(t, err)1207 buf := bytes.NewBuffer(nil)1208 require.NoError(t, r1.MakeArchive().Write(buf))1209 arc, err := lib.ReadArchive(buf)1210 require.NoError(t, err)1211 r2, err := NewFromArchive(arc, lib.RuntimeOptions{})1212 require.NoError(t, err)1213 runners := map[string]*Runner{"Source": r1, "Archive": r2}1214 for name, r := range runners {1215 t.Run(name, func(t *testing.T) {1216 ch := make(chan stats.SampleContainer, 100)1217 err = r.Setup(context.Background(), ch)1218 require.NoError(t, err)1219 vu, err := r.NewVU(ch)1220 require.NoError(t, err)1221 err = vu.RunOnce(context.Background())1222 require.NoError(t, err)1223 })1224 }1225}1226func TestArchiveNotPanicking(t *testing.T) {1227 tb := httpmultibin.NewHTTPMultiBin(t)1228 defer tb.Cleanup()1229 fs := afero.NewMemMapFs()1230 require.NoError(t, afero.WriteFile(fs, "/non/existent", []byte(`42`), os.ModePerm))1231 r1, err := getSimpleRunnerWithFileFs("/script.js", tb.Replacer.Replace(`1232 let fput = open("/non/existent");1233 export default function(data) {1234 }1235 `), fs)1236 require.NoError(t, err)1237 arc := r1.MakeArchive()1238 arc.Filesystems = map[string]afero.Fs{"file": afero.NewMemMapFs()}1239 r2, err := NewFromArchive(arc, lib.RuntimeOptions{})1240 // we do want this to error here as this is where we find out that a given file is not in the1241 // archive1242 require.Error(t, err)1243 require.Nil(t, r2)1244}1245func TestStuffNotPanicking(t *testing.T) {1246 tb := httpmultibin.NewHTTPMultiBin(t)1247 defer tb.Cleanup()1248 r, err := getSimpleRunner("/script.js", tb.Replacer.Replace(`1249 import http from "k6/http";1250 import ws from "k6/ws";1251 import { group } from "k6";1252 import { parseHTML } from "k6/html";1253 export let options = { iterations: 1, vus: 1, vusMax: 1 };1254 export default function() {1255 const doc = parseHTML(http.get("HTTPBIN_URL/html").body);1256 let testCases = [1257 () => group(),1258 () => group("test"),1259 () => group("test", "wat"),1260 () => doc.find('p').each(),1261 () => doc.find('p').each("wat"),1262 () => doc.find('p').map(),...

Full Screen

Full Screen

getSimpleRunner

Using AI Code Generation

copy

Full Screen

1import (2func main() {3 fmt.Println("Hello, playground")4 js.Global().Call("getSimpleRunner")5}6import (7func main() {8 fmt.Println("Hello, playground")9 js.Global().Call("getSimpleRunner")10}11import (12func main() {13 fmt.Println("Hello, playground")14 js.Global().Call("getSimpleRunner")15}16import (17func main() {18 fmt.Println("Hello, playground")19 js.Global().Call("getSimpleRunner")20}21import (22func main() {23 fmt.Println("Hello, playground")24 js.Global().Call("getSimpleRunner")25}26import (27func main() {28 fmt.Println("Hello, playground")29 js.Global().Call("getSimpleRunner")30}31import (32func main() {33 fmt.Println("Hello, playground")34 js.Global().Call("getSimpleRunner")35}36import (37func main() {38 fmt.Println("Hello, playground")39 js.Global().Call("getSimpleRunner")40}41import (42func main() {43 fmt.Println("Hello, playground")44 js.Global().Call("getSimpleRunner")45}46import (

Full Screen

Full Screen

getSimpleRunner

Using AI Code Generation

copy

Full Screen

1func main() {2 js.Global().Get("getSimpleRunner").Call("call", js.Global())3}4function getSimpleRunner() {5 return function() {6 console.log("Hello World");7 }8}

Full Screen

Full Screen

Automation Testing Tutorials

Learn to execute automation testing from scratch with LambdaTest Learning Hub. Right from setting up the prerequisites to run your first automation test, to following best practices and diving deeper into advanced test scenarios. LambdaTest Learning Hubs compile a list of step-by-step guides to help you be proficient with different test automation frameworks i.e. Selenium, Cypress, TestNG etc.

LambdaTest Learning Hubs:

YouTube

You could also refer to video tutorials over LambdaTest YouTube channel to get step by step demonstration from industry experts.

Run K6 automation tests on LambdaTest cloud grid

Perform automation testing on 3000+ real desktop and mobile devices online.

Most used method in

Try LambdaTest Now !!

Get 100 minutes of automation test minutes FREE!!

Next-Gen App & Browser Testing Cloud

Was this article helpful?

Helpful

NotHelpful