How to use GetBufferedSamples method of metrics Package

Best K6 code snippet using metrics.GetBufferedSamples

request_test.go

Source:request_test.go Github

copy

Full Screen

...170 _, err := rt.RunString(ctx, sr(`171 var res = http.get("HTTPBIN_URL/redirect/9");172 `))173 assert.NoError(t, err)174 bufSamples := stats.GetBufferedSamples(samples)175 reqsCount := 0176 for _, container := range bufSamples {177 for _, sample := range container.GetSamples() {178 if sample.Metric.Name == "http_reqs" {179 reqsCount++180 }181 }182 }183 assert.Equal(t, 10, reqsCount)184 assertRequestMetricsEmitted(t, bufSamples, "GET", sr("HTTPBIN_URL/redirect/9"), sr("HTTPBIN_URL/redirect/9"), 302, "")185 for i := 8; i > 0; i-- {186 url := sr(fmt.Sprintf("HTTPBIN_URL/relative-redirect/%d", i))187 assertRequestMetricsEmitted(t, bufSamples, "GET", url, url, 302, "")188 }189 assertRequestMetricsEmitted(t, bufSamples, "GET", sr("HTTPBIN_URL/get"), sr("HTTPBIN_URL/get"), 200, "")190 })191 t.Run("10", func(t *testing.T) {192 _, err := rt.RunString(ctx, sr(`http.get("HTTPBIN_URL/redirect/10")`))193 assert.NoError(t, err)194 })195 t.Run("11", func(t *testing.T) {196 _, err := rt.RunString(ctx, sr(`197 var res = http.get("HTTPBIN_URL/redirect/11");198 if (res.status != 302) { throw new Error("wrong status: " + res.status) }199 if (res.url != "HTTPBIN_URL/relative-redirect/1") { throw new Error("incorrect URL: " + res.url) }200 if (res.headers["Location"] != "/get") { throw new Error("incorrect Location header: " + res.headers["Location"]) }201 `))202 assert.NoError(t, err)203 t.Run("Unset Max", func(t *testing.T) {204 oldLogger := state.Logger205 defer func() {206 state.Logger = oldLogger207 }()208 var observedLogs *logtest.ObservedLogs209 state.Logger, observedLogs = logtest.NewObservedLogger()210 oldOpts := state.Options211 defer func() { state.Options = oldOpts }()212 state.Options.MaxRedirects = null.NewInt(10, false)213 _, err := rt.RunString(ctx, sr(`214 var res = http.get("HTTPBIN_URL/redirect/11");215 if (res.status != 302) { throw new Error("wrong status: " + res.status) }216 if (res.url != "HTTPBIN_URL/relative-redirect/1") { throw new Error("incorrect URL: " + res.url) }217 if (res.headers["Location"] != "/get") { throw new Error("incorrect Location header: " + res.headers["Location"]) }218 `))219 assert.NoError(t, err)220 exists, logEntry := logtest.LastEntry(observedLogs)221 if assert.True(t, exists) {222 assert.Equal(t, log.WarnLevel, logEntry.Level)223 assert.Equal(t, sr("HTTPBIN_URL/redirect/11"), logEntry.ContextMap()["url"])224 assert.Equal(t, "Stopped after redirects and returned the redirection; pass { redirects: n } in request params or set global maxRedirects to silence this", logEntry.Message)225 }226 })227 })228 t.Run("requestScopeRedirects", func(t *testing.T) {229 _, err := rt.RunString(ctx, sr(`230 var res = http.get("HTTPBIN_URL/redirect/1", {redirects: 3});231 if (res.status != 200) { throw new Error("wrong status: " + res.status) }232 if (res.url != "HTTPBIN_URL/get") { throw new Error("incorrect URL: " + res.url) }233 `))234 assert.NoError(t, err)235 })236 t.Run("requestScopeNoRedirects", func(t *testing.T) {237 _, err := rt.RunString(ctx, sr(`238 var res = http.get("HTTPBIN_URL/redirect/1", {redirects: 0});239 if (res.status != 302) { throw new Error("wrong status: " + res.status) }240 if (res.url != "HTTPBIN_URL/redirect/1") { throw new Error("incorrect URL: " + res.url) }241 if (res.headers["Location"] != "/get") { throw new Error("incorrect Location header: " + res.headers["Location"]) }242 `))243 assert.NoError(t, err)244 })245 t.Run("post body", func(t *testing.T) {246 tb.Mux.HandleFunc("/post-redirect", http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {247 require.Equal(t, r.Method, "POST")248 _, _ = io.Copy(ioutil.Discard, r.Body)249 http.Redirect(w, r, sr("HTTPBIN_URL/post"), http.StatusPermanentRedirect)250 }))251 _, err := rt.RunString(ctx, sr(`252 var res = http.post("HTTPBIN_URL/post-redirect", "pesho", {redirects: 1});253 if (res.status != 200) { throw new Error("wrong status: " + res.status) }254 if (res.url != "HTTPBIN_URL/post") { throw new Error("incorrect URL: " + res.url) }255 if (res.json().data != "pesho") { throw new Error("incorrect data : " + res.json().data) }256 `))257 assert.NoError(t, err)258 })259 })260 t.Run("Timeout", func(t *testing.T) {261 t.Run("10s", func(t *testing.T) {262 _, err := rt.RunString(ctx, sr(`263 http.get("HTTPBIN_URL/delay/1", {264 timeout: 5*1000,265 })266 `))267 assert.NoError(t, err)268 })269 t.Run("10s", func(t *testing.T) {270 oldLogger := state.Logger271 defer func() {272 state.Logger = oldLogger273 }()274 var observedLogs *logtest.ObservedLogs275 state.Logger, observedLogs = logtest.NewObservedLogger()276 startTime := time.Now()277 _, err := rt.RunString(ctx, sr(`278 http.get("HTTPBIN_URL/delay/10", {279 timeout: 1*1000,280 })281 `))282 endTime := time.Now()283 require.Error(t, err)284 assert.Contains(t, err.Error(), "context deadline exceeded")285 assert.WithinDuration(t, startTime.Add(1*time.Second), endTime, 2*time.Second)286 exists, _ := logtest.LastEntry(observedLogs)287 assert.True(t, exists)288 })289 t.Run("10s", func(t *testing.T) {290 oldLogger := state.Logger291 defer func() {292 state.Logger = oldLogger293 }()294 var observedLogs *logtest.ObservedLogs295 state.Logger, observedLogs = logtest.NewObservedLogger()296 startTime := time.Now()297 _, err := rt.RunString(ctx, sr(`298 http.get("HTTPBIN_URL/delay/10", {299 timeout: "1s",300 })301 `))302 endTime := time.Now()303 require.Error(t, err)304 assert.Contains(t, err.Error(), "context deadline exceeded")305 assert.WithinDuration(t, startTime.Add(1*time.Second), endTime, 2*time.Second)306 exists, _ := logtest.LastEntry(observedLogs)307 assert.True(t, exists)308 })309 })310 t.Run("UserAgent", func(t *testing.T) {311 _, err := rt.RunString(ctx, sr(`312 var res = http.get("HTTPBIN_URL/headers");313 var headers = res.json()["headers"];314 if (headers['User-Agent'] != "TestUserAgent") {315 throw new Error("incorrect user agent: " + headers['User-Agent'])316 }317 `))318 assert.NoError(t, err)319 t.Run("Override", func(t *testing.T) {320 _, err := rt.RunString(ctx, sr(`321 var res = http.get("HTTPBIN_URL/headers", {322 headers: { "User-Agent": "OtherUserAgent" },323 });324 var headers = res.json()["headers"];325 if (headers['User-Agent'] != "OtherUserAgent") {326 throw new Error("incorrect user agent: " + headers['User-Agent'])327 }328 `))329 assert.NoError(t, err)330 })331 t.Run("Override empty", func(t *testing.T) {332 _, err := rt.RunString(ctx, sr(`333 var res = http.get("HTTPBIN_URL/headers", {334 headers: { "User-Agent": "" },335 });336 var headers = res.json()["headers"]337 if (typeof headers['User-Agent'] !== 'undefined') {338 throw new Error("not undefined user agent: " + headers['User-Agent'])339 }340 `))341 assert.NoError(t, err)342 })343 t.Run("empty", func(t *testing.T) {344 oldUserAgent := state.Options.UserAgent345 defer func() {346 state.Options.UserAgent = oldUserAgent347 }()348 state.Options.UserAgent = null.NewString("", true)349 _, err := rt.RunString(ctx, sr(`350 var res = http.get("HTTPBIN_URL/headers");351 var headers = res.json()["headers"]352 if (typeof headers['User-Agent'] !== 'undefined') {353 throw new Error("not undefined user agent: " + headers['User-Agent'])354 }355 `))356 assert.NoError(t, err)357 })358 t.Run("default", func(t *testing.T) {359 oldUserAgent := state.Options.UserAgent360 defer func() {361 state.Options.UserAgent = oldUserAgent362 }()363 state.Options.UserAgent = null.NewString("Default one", false)364 _, err := rt.RunString(ctx, sr(`365 var res = http.get("HTTPBIN_URL/headers");366 var headers = res.json()["headers"]367 if (headers['User-Agent'] != "Default one") {368 throw new Error("incorrect user agent: " + headers['User-Agent'])369 }370 `))371 assert.NoError(t, err)372 })373 })374 t.Run("Compression", func(t *testing.T) {375 t.Run("gzip", func(t *testing.T) {376 _, err := rt.RunString(ctx, sr(`377 var res = http.get("HTTPSBIN_IP_URL/gzip");378 if (res.json()['gzipped'] != true) {379 throw new Error("unexpected body data: " + res.json()['gzipped'])380 }381 `))382 assert.NoError(t, err)383 })384 t.Run("deflate", func(t *testing.T) {385 _, err := rt.RunString(ctx, sr(`386 var res = http.get("HTTPBIN_URL/deflate");387 if (res.json()['deflated'] != true) {388 throw new Error("unexpected body data: " + res.json()['deflated'])389 }390 `))391 assert.NoError(t, err)392 })393 t.Run("zstd", func(t *testing.T) {394 _, err := rt.RunString(ctx, sr(`395 var res = http.get("HTTPSBIN_IP_URL/zstd");396 if (res.json()['compression'] != 'zstd') {397 throw new Error("unexpected body data: " + res.json()['compression'])398 }399 `))400 assert.NoError(t, err)401 })402 t.Run("brotli", func(t *testing.T) {403 _, err := rt.RunString(ctx, sr(`404 var res = http.get("HTTPSBIN_IP_URL/brotli");405 if (res.json()['compression'] != 'br') {406 throw new Error("unexpected body data: " + res.json()['compression'])407 }408 `))409 assert.NoError(t, err)410 })411 t.Run("zstd-br", func(t *testing.T) {412 _, err := rt.RunString(ctx, sr(`413 var res = http.get("HTTPSBIN_IP_URL/zstd-br");414 if (res.json()['compression'] != 'zstd, br') {415 throw new Error("unexpected compression: " + res.json()['compression'])416 }417 `))418 assert.NoError(t, err)419 })420 t.Run("custom compression", func(t *testing.T) {421 // We should not try to decode it422 tb.Mux.HandleFunc("/customcompression", http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {423 w.Header().Set("Content-Encoding", "custom")424 _, err := w.Write([]byte(`{"custom": true}`))425 assert.NoError(t, err)426 }))427 _, err := rt.RunString(ctx, sr(`428 var res = http.get("HTTPBIN_URL/customcompression");429 if (res.json()["custom"] != true) {430 throw new Error("unexpected body data: " + res.body)431 }432 `))433 assert.NoError(t, err)434 })435 })436 t.Run("CompressionWithAcceptEncodingHeader", func(t *testing.T) {437 t.Run("gzip", func(t *testing.T) {438 _, err := rt.RunString(ctx, sr(`439 var params = { headers: { "Accept-Encoding": "gzip" } };440 var res = http.get("HTTPBIN_URL/gzip", params);441 if (res.json()['gzipped'] != true) {442 throw new Error("unexpected body data: " + res.json()['gzipped'])443 }444 `))445 assert.NoError(t, err)446 })447 t.Run("deflate", func(t *testing.T) {448 _, err := rt.RunString(ctx, sr(`449 var params = { headers: { "Accept-Encoding": "deflate" } };450 var res = http.get("HTTPBIN_URL/deflate", params);451 if (res.json()['deflated'] != true) {452 throw new Error("unexpected body data: " + res.json()['deflated'])453 }454 `))455 assert.NoError(t, err)456 })457 })458 t.Run("Cancelled", func(t *testing.T) {459 oldLogger := state.Logger460 defer func() {461 state.Logger = oldLogger462 }()463 var observedLogs *logtest.ObservedLogs464 state.Logger, observedLogs = logtest.NewObservedLogger()465 newctx, cancel := context.WithCancel(ctx)466 cancel()467 _, err := rt.RunString(newctx, sr(`http.get("HTTPBIN_URL/get/");`))468 assert.Error(t, err)469 exists, _ := logtest.LastEntry(observedLogs)470 assert.True(t, exists)471 })472 t.Run("HTTP/2", func(t *testing.T) {473 stats.GetBufferedSamples(samples) // Clean up buffered samples from previous tests474 _, err := rt.RunString(ctx, sr(`475 var res = http.request("GET", "HTTP2BIN_URL/get");476 if (res.status != 200) { throw new Error("wrong status: " + res.status) }477 if (res.proto != "HTTP/2.0") { throw new Error("wrong proto: " + res.proto) }478 `))479 assert.NoError(t, err)480 bufSamples := stats.GetBufferedSamples(samples)481 assertRequestMetricsEmitted(t, bufSamples, "GET", sr("HTTP2BIN_URL/get"), "", 200, "")482 for _, sampleC := range bufSamples {483 for _, sample := range sampleC.GetSamples() {484 proto, ok := sample.Tags.Get("proto")485 assert.True(t, ok)486 assert.Equal(t, "HTTP/2.0", proto)487 }488 }489 })490 t.Run("TLS", func(t *testing.T) {491 t.Run("cert_expired", func(t *testing.T) {492 _, err := rt.RunString(ctx, `http.get("https://expired.badssl.com/");`)493 require.Error(t, err)494 assert.Contains(t, err.Error(), "x509: certificate has expired or is not yet valid")495 })496 tlsVersionTests := []struct {497 Name, URL, Version string498 }{499 {Name: "tls10", URL: "https://tls-v1-0.badssl.com:1010/", Version: "http.TLS_1_0"},500 {Name: "tls11", URL: "https://tls-v1-1.badssl.com:1011/", Version: "http.TLS_1_1"},501 {Name: "tls12", URL: "https://badssl.com/", Version: "http.TLS_1_2"},502 }503 for _, versionTest := range tlsVersionTests {504 t.Run(versionTest.Name, func(t *testing.T) {505 _, err := rt.RunString(ctx, fmt.Sprintf(`506 var res = http.get("%s");507 if (res.tls_version != %s) { throw new Error("wrong TLS version: " + res.tls_version); }508 `, versionTest.URL, versionTest.Version))509 assert.NoError(t, err)510 assertRequestMetricsEmitted(t, stats.GetBufferedSamples(samples), "GET", versionTest.URL, "", 200, "")511 })512 }513 tlsCipherSuiteTests := []struct {514 Name, URL, CipherSuite string515 }{516 {Name: "cipher_suite_cbc", URL: "https://cbc.badssl.com/", CipherSuite: "TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA"},517 {Name: "cipher_suite_ecc384", URL: "https://ecc384.badssl.com/", CipherSuite: "TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256"},518 }519 for _, cipherSuiteTest := range tlsCipherSuiteTests {520 t.Run(cipherSuiteTest.Name, func(t *testing.T) {521 _, err := rt.RunString(ctx, fmt.Sprintf(`522 var res = http.get("%s");523 if (res.tls_cipher_suite != "%s") { throw new Error("wrong TLS cipher suite: " + res.tls_cipher_suite); }524 `, cipherSuiteTest.URL, cipherSuiteTest.CipherSuite))525 assert.NoError(t, err)526 assertRequestMetricsEmitted(t, stats.GetBufferedSamples(samples), "GET", cipherSuiteTest.URL, "", 200, "")527 })528 }529 t.Run("ocsp_stapled_good", func(t *testing.T) {530 website := "https://www.wikipedia.org/"531 _, err := rt.RunString(ctx, fmt.Sprintf(`532 var res = http.request("GET", "%s");533 if (res.ocsp.status != http.OCSP_STATUS_GOOD) { throw new Error("wrong ocsp stapled response status: " + res.ocsp.status); }534 `, website))535 assert.NoError(t, err)536 assertRequestMetricsEmitted(t, stats.GetBufferedSamples(samples), "GET", website, "", 200, "")537 })538 })539 t.Run("Invalid", func(t *testing.T) {540 oldLogger := state.Logger541 defer func() {542 state.Logger = oldLogger543 }()544 var observedLogs *logtest.ObservedLogs545 state.Logger, observedLogs = logtest.NewObservedLogger()546 _, err := rt.RunString(ctx, `http.request("", "");`)547 require.Error(t, err)548 assert.Contains(t, err.Error(), "unsupported protocol scheme")549 exists, _ := logtest.LastEntry(observedLogs)550 assert.False(t, exists)551 t.Run("throw=false", func(t *testing.T) {552 oldLogger := state.Logger553 defer func() {554 state.Logger = oldLogger555 }()556 var observedLogs *logtest.ObservedLogs557 state.Logger, observedLogs = logtest.NewObservedLogger()558 _, err := rt.RunString(ctx, `559 var res = http.request("GET", "some://example.com", null, { throw: false });560 if (res.error.search('unsupported protocol scheme "some"') == -1) {561 throw new Error("wrong error:" + res.error);562 }563 throw new Error("another error");564 `)565 require.Error(t, err)566 assert.Contains(t, err.Error(), "another error")567 exists, logEntry := logtest.LastEntry(observedLogs)568 if assert.True(t, exists) {569 assert.Equal(t, log.WarnLevel, logEntry.Level)570 assert.Contains(t, logEntry.ContextMap()["error"].(error).Error(), "unsupported protocol scheme")571 assert.Equal(t, "Request Failed", logEntry.Message)572 }573 })574 })575 t.Run("Unroutable", func(t *testing.T) {576 _, err := rt.RunString(ctx, `http.request("GET", "http://sdafsgdhfjg/");`)577 assert.Error(t, err)578 })579 t.Run("Params", func(t *testing.T) {580 for _, literal := range []string{`undefined`, `null`} {581 t.Run(literal, func(t *testing.T) {582 _, err := rt.RunString(ctx, fmt.Sprintf(sr(`583 var res = http.request("GET", "HTTPBIN_URL/headers", null, %s);584 if (res.status != 200) { throw new Error("wrong status: " + res.status); }585 `), literal))586 assert.NoError(t, err)587 assertRequestMetricsEmitted(t, stats.GetBufferedSamples(samples), "GET", sr("HTTPBIN_URL/headers"), "", 200, "")588 })589 }590 t.Run("cookies", func(t *testing.T) {591 t.Run("access", func(t *testing.T) {592 cookieJar, err := cookiejar.New(nil)593 assert.NoError(t, err)594 state.CookieJar = cookieJar595 _, err = rt.RunString(ctx, sr(`596 var res = http.request("GET", "HTTPBIN_URL/cookies/set?key=value", null, { redirects: 0 });597 if (res.cookies.key[0].value != "value") { throw new Error("wrong cookie value: " + res.cookies.key[0].value); }598 var props = ["name", "value", "domain", "path", "expires", "max_age", "secure", "http_only"];599 var cookie = res.cookies.key[0];600 for (var i = 0; i < props.length; i++) {601 if (cookie[props[i]] === undefined) {602 throw new Error("cookie property not found: " + props[i]);603 }604 }605 if (Object.keys(cookie).length != props.length) {606 throw new Error("cookie has more properties than expected: " + JSON.stringify(Object.keys(cookie)));607 }608 `))609 assert.NoError(t, err)610 assertRequestMetricsEmitted(t, stats.GetBufferedSamples(samples), "GET", sr("HTTPBIN_URL/cookies/set?key=value"), "", 302, "")611 })612 t.Run("vuJar", func(t *testing.T) {613 cookieJar, err := cookiejar.New(nil)614 assert.NoError(t, err)615 state.CookieJar = cookieJar616 _, err = rt.RunString(ctx, sr(`617 var jar = http.cookieJar();618 jar.set("HTTPBIN_URL/cookies", "key", "value");619 var res = http.request("GET", "HTTPBIN_URL/cookies", null, { cookies: { key2: "value2" } });620 if (res.json().key != "value") { throw new Error("wrong cookie value: " + res.json().key); }621 if (res.json().key2 != "value2") { throw new Error("wrong cookie value: " + res.json().key2); }622 var jarCookies = jar.cookiesForURL("HTTPBIN_URL/cookies");623 if (jarCookies.key[0] != "value") { throw new Error("wrong cookie value in jar"); }624 if (jarCookies.key2 != undefined) { throw new Error("unexpected cookie in jar"); }625 `))626 assert.NoError(t, err)627 assertRequestMetricsEmitted(t, stats.GetBufferedSamples(samples), "GET", sr("HTTPBIN_URL/cookies"), "", 200, "")628 })629 t.Run("requestScope", func(t *testing.T) {630 cookieJar, err := cookiejar.New(nil)631 assert.NoError(t, err)632 state.CookieJar = cookieJar633 _, err = rt.RunString(ctx, sr(`634 var res = http.request("GET", "HTTPBIN_URL/cookies", null, { cookies: { key: "value" } });635 if (res.json().key != "value") { throw new Error("wrong cookie value: " + res.json().key); }636 var jar = http.cookieJar();637 var jarCookies = jar.cookiesForURL("HTTPBIN_URL/cookies");638 if (jarCookies.key != undefined) { throw new Error("unexpected cookie in jar"); }639 `))640 assert.NoError(t, err)641 assertRequestMetricsEmitted(t, stats.GetBufferedSamples(samples), "GET", sr("HTTPBIN_URL/cookies"), "", 200, "")642 })643 t.Run("requestScopeReplace", func(t *testing.T) {644 cookieJar, err := cookiejar.New(nil)645 assert.NoError(t, err)646 state.CookieJar = cookieJar647 _, err = rt.RunString(ctx, sr(`648 var jar = http.cookieJar();649 jar.set("HTTPBIN_URL/cookies", "key", "value");650 var res = http.request("GET", "HTTPBIN_URL/cookies", null, { cookies: { key: { value: "replaced", replace: true } } });651 if (res.json().key != "replaced") { throw new Error("wrong cookie value: " + res.json().key); }652 var jarCookies = jar.cookiesForURL("HTTPBIN_URL/cookies");653 if (jarCookies.key[0] != "value") { throw new Error("wrong cookie value in jar"); }654 `))655 assert.NoError(t, err)656 assertRequestMetricsEmitted(t, stats.GetBufferedSamples(samples), "GET", sr("HTTPBIN_URL/cookies"), "", 200, "")657 })658 t.Run("redirect", func(t *testing.T) {659 t.Run("set cookie after redirect", func(t *testing.T) {660 // TODO figure out a way to remove this ?661 tb.Mux.HandleFunc("/set-cookie-without-redirect", http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {662 cookie := http.Cookie{663 Name: "key-foo",664 Value: "value-bar",665 Path: "/",666 Domain: sr("HTTPSBIN_DOMAIN"),667 }668 http.SetCookie(w, &cookie)669 w.WriteHeader(200)670 }))671 cookieJar, err := cookiejar.New(nil)672 require.NoError(t, err)673 state.CookieJar = cookieJar674 _, err = rt.RunString(ctx, sr(`675 var res = http.request("GET", "HTTPBIN_URL/redirect-to?url=HTTPSBIN_URL/set-cookie-without-redirect");676 if (res.status != 200) { throw new Error("wrong status: " + res.status); }677 `))678 require.NoError(t, err)679 redirectURL, err := url.Parse(sr("HTTPSBIN_URL"))680 require.NoError(t, err)681 require.Len(t, cookieJar.Cookies(redirectURL), 1)682 require.Equal(t, "key-foo", cookieJar.Cookies(redirectURL)[0].Name)683 require.Equal(t, "value-bar", cookieJar.Cookies(redirectURL)[0].Value)684 assertRequestMetricsEmitted(685 t,686 stats.GetBufferedSamples(samples),687 "GET",688 sr("HTTPSBIN_URL/set-cookie-without-redirect"),689 sr("HTTPSBIN_URL/set-cookie-without-redirect"),690 200,691 "",692 )693 })694 t.Run("set cookie before redirect", func(t *testing.T) {695 cookieJar, err := cookiejar.New(nil)696 require.NoError(t, err)697 state.CookieJar = cookieJar698 _, err = rt.RunString(ctx, sr(`699 var res = http.request("GET", "HTTPSBIN_URL/cookies/set?key=value");700 if (res.status != 200) { throw new Error("wrong status: " + res.status); }701 `))702 require.NoError(t, err)703 redirectURL, err := url.Parse(sr("HTTPSBIN_URL/cookies"))704 require.NoError(t, err)705 require.Len(t, cookieJar.Cookies(redirectURL), 1)706 require.Equal(t, "key", cookieJar.Cookies(redirectURL)[0].Name)707 require.Equal(t, "value", cookieJar.Cookies(redirectURL)[0].Value)708 assertRequestMetricsEmitted(709 t,710 stats.GetBufferedSamples(samples),711 "GET",712 sr("HTTPSBIN_URL/cookies"),713 sr("HTTPSBIN_URL/cookies"),714 200,715 "",716 )717 })718 t.Run("set cookie after redirect and before second redirect", func(t *testing.T) {719 cookieJar, err := cookiejar.New(nil)720 require.NoError(t, err)721 state.CookieJar = cookieJar722 // TODO figure out a way to remove this ?723 tb.Mux.HandleFunc("/set-cookie-and-redirect", http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {724 cookie := http.Cookie{725 Name: "key-foo",726 Value: "value-bar",727 Path: "/set-cookie-and-redirect",728 Domain: sr("HTTPSBIN_DOMAIN"),729 }730 http.SetCookie(w, &cookie)731 http.Redirect(w, r, sr("HTTPBIN_IP_URL/get"), http.StatusMovedPermanently)732 }))733 _, err = rt.RunString(ctx, sr(`734 var res = http.request("GET", "HTTPBIN_IP_URL/redirect-to?url=HTTPSBIN_URL/set-cookie-and-redirect");735 if (res.status != 200) { throw new Error("wrong status: " + res.status); }736 `))737 require.NoError(t, err)738 redirectURL, err := url.Parse(sr("HTTPSBIN_URL/set-cookie-and-redirect"))739 require.NoError(t, err)740 require.Len(t, cookieJar.Cookies(redirectURL), 1)741 require.Equal(t, "key-foo", cookieJar.Cookies(redirectURL)[0].Name)742 require.Equal(t, "value-bar", cookieJar.Cookies(redirectURL)[0].Value)743 for _, cookieLessURL := range []string{"HTTPSBIN_URL", "HTTPBIN_IP_URL/redirect-to", "HTTPBIN_IP_URL/get"} {744 redirectURL, err = url.Parse(sr(cookieLessURL))745 require.NoError(t, err)746 require.Empty(t, cookieJar.Cookies(redirectURL))747 }748 assertRequestMetricsEmitted(749 t,750 stats.GetBufferedSamples(samples),751 "GET",752 sr("HTTPBIN_IP_URL/get"),753 sr("HTTPBIN_IP_URL/get"),754 200,755 "",756 )757 })758 })759 t.Run("domain", func(t *testing.T) {760 cookieJar, err := cookiejar.New(nil)761 assert.NoError(t, err)762 state.CookieJar = cookieJar763 _, err = rt.RunString(ctx, sr(`764 var jar = http.cookieJar();765 jar.set("HTTPBIN_URL/cookies", "key", "value", { domain: "HTTPBIN_DOMAIN" });766 var res = http.request("GET", "HTTPBIN_URL/cookies");767 if (res.json().key != "value") {768 throw new Error("wrong cookie value 1: " + res.json().key);769 }770 jar.set("HTTPBIN_URL/cookies", "key2", "value2", { domain: "example.com" });771 res = http.request("GET", "HTTPBIN_URL/cookies");772 if (res.json().key != "value") {773 throw new Error("wrong cookie value 2: " + res.json().key);774 }775 if (res.json().key2 != undefined) {776 throw new Error("cookie 'key2' unexpectedly found");777 }778 `))779 assert.NoError(t, err)780 assertRequestMetricsEmitted(t, stats.GetBufferedSamples(samples), "GET", sr("HTTPBIN_URL/cookies"), "", 200, "")781 })782 t.Run("path", func(t *testing.T) {783 cookieJar, err := cookiejar.New(nil)784 assert.NoError(t, err)785 state.CookieJar = cookieJar786 _, err = rt.RunString(ctx, sr(`787 var jar = http.cookieJar();788 jar.set("HTTPBIN_URL/cookies", "key", "value", { path: "/cookies" });789 var res = http.request("GET", "HTTPBIN_URL/cookies");790 if (res.json().key != "value") {791 throw new Error("wrong cookie value: " + res.json().key);792 }793 jar.set("HTTPBIN_URL/cookies", "key2", "value2", { path: "/some-other-path" });794 res = http.request("GET", "HTTPBIN_URL/cookies");795 if (res.json().key != "value") {796 throw new Error("wrong cookie value: " + res.json().key);797 }798 if (res.json().key2 != undefined) {799 throw new Error("cookie 'key2' unexpectedly found");800 }801 `))802 assert.NoError(t, err)803 assertRequestMetricsEmitted(t, stats.GetBufferedSamples(samples), "GET", sr("HTTPBIN_URL/cookies"), "", 200, "")804 })805 t.Run("expires", func(t *testing.T) {806 cookieJar, err := cookiejar.New(nil)807 assert.NoError(t, err)808 state.CookieJar = cookieJar809 _, err = rt.RunString(ctx, sr(`810 var jar = http.cookieJar();811 jar.set("HTTPBIN_URL/cookies", "key", "value", { expires: "Sun, 24 Jul 1983 17:01:02 GMT" });812 var res = http.request("GET", "HTTPBIN_URL/cookies");813 if (res.json().key != undefined) {814 throw new Error("cookie 'key' unexpectedly found");815 }816 jar.set("HTTPBIN_URL/cookies", "key", "value", { expires: "Sat, 24 Jul 2083 17:01:02 GMT" });817 res = http.request("GET", "HTTPBIN_URL/cookies");818 if (res.json().key != "value") {819 throw new Error("cookie 'key' not found");820 }821 `))822 assert.NoError(t, err)823 assertRequestMetricsEmitted(t, stats.GetBufferedSamples(samples), "GET", sr("HTTPBIN_URL/cookies"), "", 200, "")824 })825 t.Run("secure", func(t *testing.T) {826 cookieJar, err := cookiejar.New(nil)827 assert.NoError(t, err)828 state.CookieJar = cookieJar829 _, err = rt.RunString(ctx, sr(`830 var jar = http.cookieJar();831 jar.set("HTTPSBIN_IP_URL/cookies", "key", "value", { secure: true });832 var res = http.request("GET", "HTTPSBIN_IP_URL/cookies");833 if (res.json().key != "value") {834 throw new Error("wrong cookie value: " + res.json().key);835 }836 `))837 assert.NoError(t, err)838 assertRequestMetricsEmitted(t, stats.GetBufferedSamples(samples), "GET", sr("HTTPSBIN_IP_URL/cookies"), "", 200, "")839 })840 t.Run("localJar", func(t *testing.T) {841 cookieJar, err := cookiejar.New(nil)842 assert.NoError(t, err)843 state.CookieJar = cookieJar844 _, err = rt.RunString(ctx, sr(`845 var jar = new http.CookieJar();846 jar.set("HTTPBIN_URL/cookies", "key", "value");847 var res = http.request("GET", "HTTPBIN_URL/cookies", null, { cookies: { key2: "value2" }, jar: jar });848 if (res.json().key != "value") { throw new Error("wrong cookie value: " + res.json().key); }849 if (res.json().key2 != "value2") { throw new Error("wrong cookie value: " + res.json().key2); }850 var jarCookies = jar.cookiesForURL("HTTPBIN_URL/cookies");851 if (jarCookies.key[0] != "value") { throw new Error("wrong cookie value in jar: " + jarCookies.key[0]); }852 if (jarCookies.key2 != undefined) { throw new Error("unexpected cookie in jar"); }853 `))854 assert.NoError(t, err)855 assertRequestMetricsEmitted(t, stats.GetBufferedSamples(samples), "GET", sr("HTTPBIN_URL/cookies"), "", 200, "")856 })857 })858 t.Run("auth", func(t *testing.T) {859 t.Run("basic", func(t *testing.T) {860 url := sr("http://bob:pass@HTTPBIN_IP:HTTPBIN_PORT/basic-auth/bob/pass")861 urlExpected := sr("http://****:****@HTTPBIN_IP:HTTPBIN_PORT/basic-auth/bob/pass")862 _, err := rt.RunString(ctx, fmt.Sprintf(`863 var res = http.request("GET", "%s", null, {});864 if (res.status != 200) { throw new Error("wrong status: " + res.status); }865 `, url))866 assert.NoError(t, err)867 assertRequestMetricsEmitted(t, stats.GetBufferedSamples(samples), "GET", urlExpected, urlExpected, 200, "")868 })869 t.Run("digest", func(t *testing.T) {870 t.Run("success", func(t *testing.T) {871 url := sr("http://bob:pass@HTTPBIN_IP:HTTPBIN_PORT/digest-auth/auth/bob/pass")872 urlRaw := sr("HTTPBIN_IP_URL/digest-auth/auth/bob/pass")873 _, err := rt.RunString(ctx, fmt.Sprintf(`874 var res = http.request("GET", "%s", null, { auth: "digest" });875 if (res.status != 200) { throw new Error("wrong status: " + res.status); }876 if (res.error_code != 0) { throw new Error("wrong error code: " + res.error_code); }877 `, url))878 assert.NoError(t, err)879 sampleContainers := stats.GetBufferedSamples(samples)880 assertRequestMetricsEmitted(t, sampleContainers[0:1], "GET",881 urlRaw, urlRaw, 401, "")882 assertRequestMetricsEmitted(t, sampleContainers[1:2], "GET",883 urlRaw, urlRaw, 200, "")884 })885 t.Run("failure", func(t *testing.T) {886 url := sr("http://bob:pass@HTTPBIN_IP:HTTPBIN_PORT/digest-auth/failure")887 _, err := rt.RunString(ctx, fmt.Sprintf(`888 var res = http.request("GET", "%s", null, { auth: "digest", timeout: 1, throw: false });889 `, url))890 assert.NoError(t, err)891 })892 })893 })894 t.Run("headers", func(t *testing.T) {895 for _, literal := range []string{`null`, `undefined`} {896 t.Run(literal, func(t *testing.T) {897 _, err := rt.RunString(ctx, fmt.Sprintf(sr(`898 var res = http.request("GET", "HTTPBIN_URL/headers", null, { headers: %s });899 if (res.status != 200) { throw new Error("wrong status: " + res.status); }900 `), literal))901 assert.NoError(t, err)902 assertRequestMetricsEmitted(t, stats.GetBufferedSamples(samples), "GET", sr("HTTPBIN_URL/headers"), "", 200, "")903 })904 }905 t.Run("object", func(t *testing.T) {906 _, err := rt.RunString(ctx, sr(`907 var res = http.request("GET", "HTTPBIN_URL/headers", null, {908 headers: { "X-My-Header": "value" },909 });910 if (res.status != 200) { throw new Error("wrong status: " + res.status); }911 if (res.json().headers["X-My-Header"] != "value") { throw new Error("wrong X-My-Header: " + res.json().headers["X-My-Header"]); }912 `))913 assert.NoError(t, err)914 assertRequestMetricsEmitted(t, stats.GetBufferedSamples(samples), "GET", sr("HTTPBIN_URL/headers"), "", 200, "")915 })916 t.Run("Host", func(t *testing.T) {917 _, err := rt.RunString(ctx, sr(`918 var res = http.request("GET", "HTTPBIN_URL/headers", null, {919 headers: { "Host": "HTTPBIN_DOMAIN" },920 });921 if (res.status != 200) { throw new Error("wrong status: " + res.status); }922 if (res.json().headers["Host"] != "HTTPBIN_DOMAIN") { throw new Error("wrong Host: " + res.json().headers["Host"]); }923 `))924 assert.NoError(t, err)925 assertRequestMetricsEmitted(t, stats.GetBufferedSamples(samples), "GET", sr("HTTPBIN_URL/headers"), "", 200, "")926 })927 t.Run("response_request", func(t *testing.T) {928 _, err := rt.RunString(ctx, sr(`929 var res = http.request("GET", "HTTPBIN_URL/headers", null, {930 headers: { "host": "HTTPBIN_DOMAIN" },931 });932 if (res.status != 200) { throw new Error("wrong status: " + res.status); }933 if (res.request.headers["Host"] != "HTTPBIN_DOMAIN") { throw new Error("wrong Host: " + res.request.headers["Host"]); }934 `))935 assert.NoError(t, err)936 assertRequestMetricsEmitted(t, stats.GetBufferedSamples(samples), "GET", sr("HTTPBIN_URL/headers"), "", 200, "")937 })938 t.Run("differentHost", func(t *testing.T) {939 _, err := rt.RunString(ctx, sr(`940 var custHost = 'k6.io';941 var res = http.request("GET", "HTTPBIN_URL/headers", null, {942 headers: { "host": custHost },943 });944 if (res.status != 200) { throw new Error("wrong status: " + res.status); }945 if (res.request.headers["Host"] != custHost) { throw new Error("wrong Host: " + res.request.headers["Host"]); }946 `))947 assert.NoError(t, err)948 assertRequestMetricsEmitted(t, stats.GetBufferedSamples(samples), "GET", sr("HTTPBIN_URL/headers"), "", 200, "")949 })950 })951 t.Run("tags", func(t *testing.T) {952 for _, literal := range []string{`null`, `undefined`} {953 t.Run(literal, func(t *testing.T) {954 _, err := rt.RunString(ctx, fmt.Sprintf(sr(`955 var res = http.request("GET", "HTTPBIN_URL/headers", null, { tags: %s });956 if (res.status != 200) { throw new Error("wrong status: " + res.status); }957 `), literal))958 assert.NoError(t, err)959 assertRequestMetricsEmitted(t, stats.GetBufferedSamples(samples), "GET", sr("HTTPBIN_URL/headers"), "", 200, "")960 })961 }962 t.Run("name/none", func(t *testing.T) {963 _, err := rt.RunString(ctx, sr(`964 var res = http.request("GET", "HTTPBIN_URL/headers");965 if (res.status != 200) { throw new Error("wrong status: " + res.status); }966 `))967 assert.NoError(t, err)968 assertRequestMetricsEmitted(t, stats.GetBufferedSamples(samples), "GET",969 sr("HTTPBIN_URL/headers"), sr("HTTPBIN_URL/headers"), 200, "")970 })971 t.Run("name/request", func(t *testing.T) {972 _, err := rt.RunString(ctx, sr(`973 var res = http.request("GET", "HTTPBIN_URL/headers", null, { tags: { name: "myReq" }});974 if (res.status != 200) { throw new Error("wrong status: " + res.status); }975 `))976 assert.NoError(t, err)977 assertRequestMetricsEmitted(t, stats.GetBufferedSamples(samples), "GET",978 sr("HTTPBIN_URL/headers"), "myReq", 200, "")979 })980 t.Run("name/template", func(t *testing.T) {981 _, err := runES6String(t, ctx, rt, "http.get(http.url`"+sr(`HTTPBIN_URL/anything/${1+1}`)+"`);")982 assert.NoError(t, err)983 // There's no /anything endpoint in the go-httpbin library we're using, hence the 404,984 // but it doesn't matter for this test.985 assertRequestMetricsEmitted(t, stats.GetBufferedSamples(samples), "GET",986 sr("HTTPBIN_URL/anything/2"), sr("HTTPBIN_URL/anything/${}"), 404, "")987 })988 t.Run("object", func(t *testing.T) {989 _, err := rt.RunString(ctx, sr(`990 var res = http.request("GET", "HTTPBIN_URL/headers", null, { tags: { tag: "value" } });991 if (res.status != 200) { throw new Error("wrong status: " + res.status); }992 `))993 assert.NoError(t, err)994 bufSamples := stats.GetBufferedSamples(samples)995 assertRequestMetricsEmitted(t, bufSamples, "GET", sr("HTTPBIN_URL/headers"), "", 200, "")996 for _, sampleC := range bufSamples {997 for _, sample := range sampleC.GetSamples() {998 tagValue, ok := sample.Tags.Get("tag")999 assert.True(t, ok)1000 assert.Equal(t, "value", tagValue)1001 }1002 }1003 })1004 t.Run("tags-precedence", func(t *testing.T) {1005 oldTags := state.Tags1006 defer func() { state.Tags = oldTags }()1007 state.Tags = map[string]string{"runtag1": "val1", "runtag2": "val2"}1008 _, err := rt.RunString(ctx, sr(`1009 var res = http.request("GET", "HTTPBIN_URL/headers", null, { tags: { method: "test", name: "myName", runtag1: "fromreq" } });1010 if (res.status != 200) { throw new Error("wrong status: " + res.status); }1011 `))1012 assert.NoError(t, err)1013 bufSamples := stats.GetBufferedSamples(samples)1014 assertRequestMetricsEmitted(t, bufSamples, "GET", sr("HTTPBIN_URL/headers"), "myName", 200, "")1015 for _, sampleC := range bufSamples {1016 for _, sample := range sampleC.GetSamples() {1017 tagValue, ok := sample.Tags.Get("method")1018 assert.True(t, ok)1019 assert.Equal(t, "GET", tagValue)1020 tagValue, ok = sample.Tags.Get("name")1021 assert.True(t, ok)1022 assert.Equal(t, "myName", tagValue)1023 tagValue, ok = sample.Tags.Get("runtag1")1024 assert.True(t, ok)1025 assert.Equal(t, "fromreq", tagValue)1026 tagValue, ok = sample.Tags.Get("runtag2")1027 assert.True(t, ok)1028 assert.Equal(t, "val2", tagValue)1029 }1030 }1031 })1032 })1033 })1034 t.Run("GET", func(t *testing.T) {1035 _, err := rt.RunString(ctx, sr(`1036 var res = http.get("HTTPBIN_URL/get?a=1&b=2");1037 if (res.status != 200) { throw new Error("wrong status: " + res.status); }1038 if (res.json().args.a != "1") { throw new Error("wrong ?a: " + res.json().args.a); }1039 if (res.json().args.b != "2") { throw new Error("wrong ?b: " + res.json().args.b); }1040 `))1041 assert.NoError(t, err)1042 assertRequestMetricsEmitted(t, stats.GetBufferedSamples(samples), "GET", sr("HTTPBIN_URL/get?a=1&b=2"), "", 200, "")1043 t.Run("Tagged", func(t *testing.T) {1044 _, err := runES6String(t, ctx, rt, `1045 var a = "1";1046 var b = "2";1047 var res = http.get(http.url`+"`"+sr(`HTTPBIN_URL/get?a=${a}&b=${b}`)+"`"+`);1048 if (res.status != 200) { throw new Error("wrong status: " + res.status); }1049 if (res.json().args.a != a) { throw new Error("wrong ?a: " + res.json().args.a); }1050 if (res.json().args.b != b) { throw new Error("wrong ?b: " + res.json().args.b); }1051 `)1052 assert.NoError(t, err)1053 assertRequestMetricsEmitted(t, stats.GetBufferedSamples(samples), "GET", sr("HTTPBIN_URL/get?a=1&b=2"), sr("HTTPBIN_URL/get?a=${}&b=${}"), 200, "")1054 })1055 })1056 t.Run("HEAD", func(t *testing.T) {1057 _, err := rt.RunString(ctx, sr(`1058 var res = http.head("HTTPBIN_URL/get?a=1&b=2");1059 if (res.status != 200) { throw new Error("wrong status: " + res.status); }1060 if (res.body.length != 0) { throw new Error("HEAD responses shouldn't have a body"); }1061 if (!res.headers["Content-Length"]) { throw new Error("Missing or invalid Content-Length header!"); }1062 `))1063 assert.NoError(t, err)1064 assertRequestMetricsEmitted(t, stats.GetBufferedSamples(samples), "HEAD", sr("HTTPBIN_URL/get?a=1&b=2"), "", 200, "")1065 })1066 t.Run("OPTIONS", func(t *testing.T) {1067 _, err := rt.RunString(ctx, sr(`1068 var res = http.options("HTTPBIN_URL/?a=1&b=2");1069 if (res.status != 200) { throw new Error("wrong status: " + res.status); }1070 if (!res.headers["Access-Control-Allow-Methods"]) { throw new Error("Missing Access-Control-Allow-Methods header!"); }1071 `))1072 assert.NoError(t, err)1073 assertRequestMetricsEmitted(t, stats.GetBufferedSamples(samples), "OPTIONS", sr("HTTPBIN_URL/?a=1&b=2"), "", 200, "")1074 })1075 // DELETE HTTP requests shouldn't usually send a request body, they should use url parameters instead; references:1076 // https://golang.org/pkg/net/http/#Request.ParseForm1077 // https://stackoverflow.com/questions/299628/is-an-entity-body-allowed-for-an-http-delete-request1078 // https://tools.ietf.org/html/rfc7231#section-4.3.51079 t.Run("DELETE", func(t *testing.T) {1080 _, err := rt.RunString(ctx, sr(`1081 var res = http.del("HTTPBIN_URL/delete?test=mest");1082 if (res.status != 200) { throw new Error("wrong status: " + res.status); }1083 if (res.json().args.test != "mest") { throw new Error("wrong args: " + JSON.stringify(res.json().args)); }1084 `))1085 assert.NoError(t, err)1086 assertRequestMetricsEmitted(t, stats.GetBufferedSamples(samples), "DELETE", sr("HTTPBIN_URL/delete?test=mest"), "", 200, "")1087 })1088 postMethods := map[string]string{1089 "POST": "post",1090 "PUT": "put",1091 "PATCH": "patch",1092 }1093 for method, fn := range postMethods {1094 t.Run(method, func(t *testing.T) {1095 _, err := rt.RunString(ctx, fmt.Sprintf(sr(`1096 var res = http.%s("HTTPBIN_URL/%s", "data");1097 if (res.status != 200) { throw new Error("wrong status: " + res.status); }1098 if (res.json().data != "data") { throw new Error("wrong data: " + res.json().data); }1099 if (res.json().headers["Content-Type"]) { throw new Error("content type set: " + res.json().headers["Content-Type"]); }1100 `), fn, strings.ToLower(method)))1101 assert.NoError(t, err)1102 assertRequestMetricsEmitted(t, stats.GetBufferedSamples(samples), method, sr("HTTPBIN_URL/")+strings.ToLower(method), "", 200, "")1103 t.Run("object", func(t *testing.T) {1104 _, err := rt.RunString(ctx, fmt.Sprintf(sr(`1105 var res = http.%s("HTTPBIN_URL/%s", {a: "a", b: 2});1106 if (res.status != 200) { throw new Error("wrong status: " + res.status); }1107 if (res.json().form.a != "a") { throw new Error("wrong a=: " + res.json().form.a); }1108 if (res.json().form.b != "2") { throw new Error("wrong b=: " + res.json().form.b); }1109 if (res.json().headers["Content-Type"] != "application/x-www-form-urlencoded") { throw new Error("wrong content type: " + res.json().headers["Content-Type"]); }1110 `), fn, strings.ToLower(method)))1111 assert.NoError(t, err)1112 assertRequestMetricsEmitted(t, stats.GetBufferedSamples(samples), method, sr("HTTPBIN_URL/")+strings.ToLower(method), "", 200, "")1113 t.Run("Content-Type", func(t *testing.T) {1114 _, err := rt.RunString(ctx, fmt.Sprintf(sr(`1115 var res = http.%s("HTTPBIN_URL/%s", {a: "a", b: 2}, {headers: {"Content-Type": "application/x-www-form-urlencoded; charset=utf-8"}});1116 if (res.status != 200) { throw new Error("wrong status: " + res.status); }1117 if (res.json().form.a != "a") { throw new Error("wrong a=: " + res.json().form.a); }1118 if (res.json().form.b != "2") { throw new Error("wrong b=: " + res.json().form.b); }1119 if (res.json().headers["Content-Type"] != "application/x-www-form-urlencoded; charset=utf-8") { throw new Error("wrong content type: " + res.json().headers["Content-Type"]); }1120 `), fn, strings.ToLower(method)))1121 assert.NoError(t, err)1122 assertRequestMetricsEmitted(t, stats.GetBufferedSamples(samples), method, sr("HTTPBIN_URL/")+strings.ToLower(method), "", 200, "")1123 })1124 })1125 })1126 }1127 t.Run("Batch", func(t *testing.T) {1128 t.Run("error", func(t *testing.T) {1129 _, err := rt.RunString(ctx, `var res = http.batch("https://somevalidurl.com");`)1130 require.Error(t, err)1131 })1132 t.Run("GET", func(t *testing.T) {1133 _, err := rt.RunString(ctx, sr(`1134 var reqs = [1135 ["GET", "HTTPBIN_URL/"],1136 ["GET", "HTTPBIN_IP_URL/"],1137 ];1138 var res = http.batch(reqs);1139 for (var key in res) {1140 if (res[key].status != 200) { throw new Error("wrong status: " + res[key].status); }1141 if (res[key].url != reqs[key][1]) { throw new Error("wrong url: " + res[key].url); }1142 }`))1143 require.NoError(t, err)1144 bufSamples := stats.GetBufferedSamples(samples)1145 assertRequestMetricsEmitted(t, bufSamples, "GET", sr("HTTPBIN_URL/"), "", 200, "")1146 assertRequestMetricsEmitted(t, bufSamples, "GET", sr("HTTPBIN_IP_URL/"), "", 200, "")1147 t.Run("Tagged", func(t *testing.T) {1148 _, err := runES6String(t, ctx, rt, sr(`1149 let fragment = "get";1150 let reqs = [1151 ["GET", http.url`+"`"+`HTTPBIN_URL/${fragment}`+"`"+`],1152 ["GET", http.url`+"`"+`HTTPBIN_IP_URL/`+"`"+`],1153 ];1154 let res = http.batch(reqs);1155 for (var key in res) {1156 if (res[key].status != 200) { throw new Error("wrong status: " + key + ": " + res[key].status); }1157 if (res[key].url != reqs[key][1].url) { throw new Error("wrong url: " + key + ": " + res[key].url + " != " + reqs[key][1].url); }1158 }`))1159 assert.NoError(t, err)1160 bufSamples := stats.GetBufferedSamples(samples)1161 assertRequestMetricsEmitted(t, bufSamples, "GET", sr("HTTPBIN_URL/get"), sr("HTTPBIN_URL/${}"), 200, "")1162 assertRequestMetricsEmitted(t, bufSamples, "GET", sr("HTTPBIN_IP_URL/"), "", 200, "")1163 })1164 t.Run("Shorthand", func(t *testing.T) {1165 _, err := rt.RunString(ctx, sr(`1166 var reqs = [1167 "HTTPBIN_URL/",1168 "HTTPBIN_IP_URL/",1169 ];1170 var res = http.batch(reqs);1171 for (var key in res) {1172 if (res[key].status != 200) { throw new Error("wrong status: " + key + ": " + res[key].status); }1173 if (res[key].url != reqs[key]) { throw new Error("wrong url: " + key + ": " + res[key].url); }1174 }`))1175 assert.NoError(t, err)1176 bufSamples := stats.GetBufferedSamples(samples)1177 assertRequestMetricsEmitted(t, bufSamples, "GET", sr("HTTPBIN_URL/"), "", 200, "")1178 assertRequestMetricsEmitted(t, bufSamples, "GET", sr("HTTPBIN_IP_URL/"), "", 200, "")1179 t.Run("Tagged", func(t *testing.T) {1180 _, err := runES6String(t, ctx, rt, sr(`1181 let fragment = "get";1182 let reqs = [1183 http.url`+"`"+`HTTPBIN_URL/${fragment}`+"`"+`,1184 http.url`+"`"+`HTTPBIN_IP_URL/`+"`"+`,1185 ];1186 let res = http.batch(reqs);1187 for (var key in res) {1188 if (res[key].status != 200) { throw new Error("wrong status: " + key + ": " + res[key].status); }1189 if (res[key].url != reqs[key].url) { throw new Error("wrong url: " + key + ": " + res[key].url + " != " + reqs[key].url); }1190 }`))1191 assert.NoError(t, err)1192 bufSamples := stats.GetBufferedSamples(samples)1193 assertRequestMetricsEmitted(t, bufSamples, "GET", sr("HTTPBIN_URL/get"), sr("HTTPBIN_URL/${}"), 200, "")1194 assertRequestMetricsEmitted(t, bufSamples, "GET", sr("HTTPBIN_IP_URL/"), "", 200, "")1195 })1196 })1197 t.Run("ObjectForm", func(t *testing.T) {1198 _, err := rt.RunString(ctx, sr(`1199 var reqs = [1200 { method: "GET", url: "HTTPBIN_URL/" },1201 { url: "HTTPBIN_IP_URL/", method: "GET"},1202 ];1203 var res = http.batch(reqs);1204 for (var key in res) {1205 if (res[key].status != 200) { throw new Error("wrong status: " + key + ": " + res[key].status); }1206 if (res[key].url != reqs[key].url) { throw new Error("wrong url: " + key + ": " + res[key].url + " != " + reqs[key].url); }1207 }`))1208 assert.NoError(t, err)1209 bufSamples := stats.GetBufferedSamples(samples)1210 assertRequestMetricsEmitted(t, bufSamples, "GET", sr("HTTPBIN_URL/"), "", 200, "")1211 assertRequestMetricsEmitted(t, bufSamples, "GET", sr("HTTPBIN_IP_URL/"), "", 200, "")1212 })1213 t.Run("ObjectKeys", func(t *testing.T) {1214 _, err := rt.RunString(ctx, sr(`1215 var reqs = {1216 shorthand: "HTTPBIN_URL/get?r=shorthand",1217 arr: ["GET", "HTTPBIN_URL/get?r=arr", null, {tags: {name: 'arr'}}],1218 obj1: { method: "GET", url: "HTTPBIN_URL/get?r=obj1" },1219 obj2: { url: "HTTPBIN_URL/get?r=obj2", params: {tags: {name: 'obj2'}}, method: "GET"},1220 };1221 var res = http.batch(reqs);1222 for (var key in res) {1223 if (res[key].status != 200) { throw new Error("wrong status: " + key + ": " + res[key].status); }1224 if (res[key].json().args.r != key) { throw new Error("wrong request id: " + key); }1225 }`))1226 assert.NoError(t, err)1227 bufSamples := stats.GetBufferedSamples(samples)1228 assertRequestMetricsEmitted(t, bufSamples, "GET", sr("HTTPBIN_URL/get?r=shorthand"), "", 200, "")1229 assertRequestMetricsEmitted(t, bufSamples, "GET", sr("HTTPBIN_URL/get?r=arr"), "arr", 200, "")1230 assertRequestMetricsEmitted(t, bufSamples, "GET", sr("HTTPBIN_URL/get?r=obj1"), "", 200, "")1231 assertRequestMetricsEmitted(t, bufSamples, "GET", sr("HTTPBIN_URL/get?r=obj2"), "obj2", 200, "")1232 })1233 t.Run("BodyAndParams", func(t *testing.T) {1234 testStr := "testbody"1235 rt.Set("someStrFile", testStr)1236 rt.Set("someBinFile", []byte(testStr))1237 _, err := rt.RunString(ctx, sr(`1238 var reqs = [1239 ["POST", "HTTPBIN_URL/post", "testbody"],1240 ["POST", "HTTPBIN_URL/post", someStrFile],1241 ["POST", "HTTPBIN_URL/post", someBinFile],1242 {1243 method: "POST",1244 url: "HTTPBIN_URL/post",1245 test: "test1",1246 body: "testbody",1247 }, {1248 body: someBinFile,1249 url: "HTTPBIN_IP_URL/post",1250 params: { tags: { name: "myname" } },1251 method: "POST",1252 }, {1253 method: "POST",1254 url: "HTTPBIN_IP_URL/post",1255 body: {1256 hello: "world!",1257 },1258 params: {1259 tags: { name: "myname" },1260 headers: { "Content-Type": "application/x-www-form-urlencoded" },1261 },1262 },1263 ];1264 var res = http.batch(reqs);1265 for (var key in res) {1266 if (res[key].status != 200) { throw new Error("wrong status: " + key + ": " + res[key].status); }1267 if (res[key].json().data != "testbody" && res[key].json().form.hello != "world!") { throw new Error("wrong response for " + key + ": " + res[key].body); }1268 }`))1269 assert.NoError(t, err)1270 bufSamples := stats.GetBufferedSamples(samples)1271 assertRequestMetricsEmitted(t, bufSamples, "POST", sr("HTTPBIN_URL/post"), "", 200, "")1272 assertRequestMetricsEmitted(t, bufSamples, "POST", sr("HTTPBIN_IP_URL/post"), "myname", 200, "")1273 })1274 })1275 t.Run("POST", func(t *testing.T) {1276 _, err := rt.RunString(ctx, sr(`1277 var res = http.batch([ ["POST", "HTTPBIN_URL/post", { key: "value" }] ]);1278 for (var key in res) {1279 if (res[key].status != 200) { throw new Error("wrong status: " + key + ": " + res[key].status); }1280 if (res[key].json().form.key != "value") { throw new Error("wrong form: " + key + ": " + JSON.stringify(res[key].json().form)); }1281 }`))1282 assert.NoError(t, err)1283 assertRequestMetricsEmitted(t, stats.GetBufferedSamples(samples), "POST", sr("HTTPBIN_URL/post"), "", 200, "")1284 })1285 t.Run("PUT", func(t *testing.T) {1286 _, err := rt.RunString(ctx, sr(`1287 var res = http.batch([ ["PUT", "HTTPBIN_URL/put", { key: "value" }] ]);1288 for (var key in res) {1289 if (res[key].status != 200) { throw new Error("wrong status: " + key + ": " + res[key].status); }1290 if (res[key].json().form.key != "value") { throw new Error("wrong form: " + key + ": " + JSON.stringify(res[key].json().form)); }1291 }`))1292 assert.NoError(t, err)1293 assertRequestMetricsEmitted(t, stats.GetBufferedSamples(samples), "PUT", sr("HTTPBIN_URL/put"), "", 200, "")1294 })1295 })1296 t.Run("HTTPRequest", func(t *testing.T) {1297 t.Run("EmptyBody", func(t *testing.T) {1298 _, err := rt.RunString(ctx, sr(`1299 var reqUrl = "HTTPBIN_URL/cookies"1300 var res = http.get(reqUrl);1301 var jar = new http.CookieJar();1302 jar.set("HTTPBIN_URL/cookies", "key", "value");1303 res = http.request("GET", "HTTPBIN_URL/cookies", null, { cookies: { key2: "value2" }, jar: jar });1304 if (res.json().key != "value") { throw new Error("wrong cookie value: " + res.json().key); }1305 if (res.status != 200) { throw new Error("wrong status: " + res.status); }1306 if (res.request["method"] !== "GET") { throw new Error("http request method was not \"GET\": " + JSON.stringify(res.request)) }1307 if (res.request["body"].length != 0) { throw new Error("http request body was not null: " + JSON.stringify(res.request["body"])) }1308 if (res.request["url"] != reqUrl) {1309 throw new Error("wrong http request url: " + JSON.stringify(res.request))1310 }1311 if (res.request["cookies"]["key2"][0].name != "key2") { throw new Error("wrong http request cookies: " + JSON.stringify(JSON.stringify(res.request["cookies"]["key2"]))) }1312 if (res.request["headers"]["User-Agent"][0] != "TestUserAgent") { throw new Error("wrong http request headers: " + JSON.stringify(res.request)) }1313 `))1314 assert.NoError(t, err)1315 })1316 t.Run("NonEmptyBody", func(t *testing.T) {1317 _, err := rt.RunString(ctx, sr(`1318 var res = http.post("HTTPBIN_URL/post", {a: "a", b: 2}, {headers: {"Content-Type": "application/x-www-form-urlencoded; charset=utf-8"}});1319 if (res.status != 200) { throw new Error("wrong status: " + res.status); }1320 if (res.request["body"] != "a=a&b=2") { throw new Error("http request body was not set properly: " + JSON.stringify(res.request))}1321 `))1322 assert.NoError(t, err)1323 })1324 })1325}1326func TestRequestArrayBufferBody(t *testing.T) {1327 t.Parallel()1328 tb, _, _, rt, ctx := newRuntime(t) //nolint: dogsled1329 defer tb.Cleanup()1330 sr := tb.Replacer.Replace1331 tb.Mux.HandleFunc("/post-arraybuffer", http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {1332 require.Equal(t, "POST", r.Method)1333 var in bytes.Buffer1334 _, err := io.Copy(&in, r.Body)1335 require.NoError(t, err)1336 _, err = w.Write(in.Bytes())1337 require.NoError(t, err)1338 }))1339 testCases := []struct {1340 arr, expected string1341 }{1342 {"Uint8Array", "104,101,108,108,111"},1343 {"Uint16Array", "104,0,101,0,108,0,108,0,111,0"},1344 {"Uint32Array", "104,0,0,0,101,0,0,0,108,0,0,0,108,0,0,0,111,0,0,0"},1345 }1346 for _, tc := range testCases {1347 tc := tc1348 t.Run(tc.arr, func(t *testing.T) {1349 _, err := rt.RunString(ctx, sr(fmt.Sprintf(`1350 var arr = new %[1]s([104, 101, 108, 108, 111]); // "hello"1351 var res = http.post("HTTPBIN_URL/post-arraybuffer", arr.buffer, { responseType: 'binary' });1352 if (res.status != 200) { throw new Error("wrong status: " + res.status) }1353 if (res.body != "%[2]s") { throw new Error(1354 "incorrect data: expected '%[2]s', received '" + res.body + "'") }1355 `, tc.arr, tc.expected)))1356 assert.NoError(t, err)1357 })1358 }1359}1360func TestRequestCompression(t *testing.T) {1361 t.Parallel()1362 tb, state, _, rt, ctx := newRuntime(t)1363 defer tb.Cleanup()1364 var observedLogs *logtest.ObservedLogs1365 state.Logger, observedLogs = logtest.NewObservedLogger()1366 // We don't expect any failed requests1367 state.Options.Throw = null.BoolFrom(true)1368 text := `1369 Lorem ipsum dolor sit amet, consectetur adipiscing elit.1370 Maecenas sed pharetra sapien. Nunc laoreet molestie ante ac gravida.1371 Etiam interdum dui viverra posuere egestas. Pellentesque at dolor tristique,1372 mattis turpis eget, commodo purus. Nunc orci aliquam.`1373 decompress := func(algo string, input io.Reader) io.Reader {1374 switch algo {1375 case "br":1376 w := brotli.NewReader(input)1377 return w1378 case "gzip":1379 w, err := gzip.NewReader(input)1380 if err != nil {1381 t.Fatal(err)1382 }1383 return w1384 case "deflate":1385 w, err := zlib.NewReader(input)1386 if err != nil {1387 t.Fatal(err)1388 }1389 return w1390 case "zstd":1391 w, err := zstd.NewReader(input)1392 if err != nil {1393 t.Fatal(err)1394 }1395 return w1396 default:1397 t.Fatal("unknown algorithm " + algo)1398 }1399 return nil // unreachable1400 }1401 var (1402 expectedEncoding string1403 actualEncoding string1404 )1405 tb.Mux.HandleFunc("/compressed-text", http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {1406 require.Equal(t, expectedEncoding, r.Header.Get("Content-Encoding"))1407 expectedLength, err := strconv.Atoi(r.Header.Get("Content-Length"))1408 require.NoError(t, err)1409 algos := strings.Split(actualEncoding, ", ")1410 compressedBuf := new(bytes.Buffer)1411 n, err := io.Copy(compressedBuf, r.Body)1412 require.Equal(t, int(n), expectedLength)1413 require.NoError(t, err)1414 var prev io.Reader = compressedBuf1415 if expectedEncoding != "" {1416 for i := len(algos) - 1; i >= 0; i-- {1417 prev = decompress(algos[i], prev)1418 }1419 }1420 var buf bytes.Buffer1421 _, err = io.Copy(&buf, prev)1422 require.NoError(t, err)1423 require.Equal(t, text, buf.String())1424 }))1425 testCases := []struct {1426 name string1427 compression string1428 expectedError string1429 }{1430 {compression: ""},1431 {compression: " "},1432 {compression: "gzip"},1433 {compression: "gzip, gzip"},1434 {compression: "gzip, gzip "},1435 {compression: "gzip,gzip"},1436 {compression: "gzip, gzip, gzip, gzip, gzip, gzip, gzip"},1437 {compression: "deflate"},1438 {compression: "deflate, gzip"},1439 {compression: "gzip,deflate, gzip"},1440 {compression: "zstd"},1441 {compression: "zstd, gzip, deflate"},1442 {compression: "br"},1443 {compression: "br, gzip, deflate"},1444 {1445 compression: "George",1446 expectedError: `unknown compression algorithm George`,1447 },1448 {1449 compression: "gzip, George",1450 expectedError: `unknown compression algorithm George`,1451 },1452 }1453 for _, testCase := range testCases {1454 testCase := testCase1455 t.Run(testCase.compression, func(t *testing.T) {1456 algos := strings.Split(testCase.compression, ",")1457 for i, algo := range algos {1458 algos[i] = strings.TrimSpace(algo)1459 }1460 expectedEncoding = strings.Join(algos, ", ")1461 actualEncoding = expectedEncoding1462 _, err := runES6String(t, ctx, rt, tb.Replacer.Replace(`1463 http.post("HTTPBIN_URL/compressed-text", `+"`"+text+"`"+`, {"compression": "`+testCase.compression+`"});1464 `))1465 if testCase.expectedError == "" {1466 require.NoError(t, err)1467 } else {1468 require.Error(t, err)1469 require.Contains(t, err.Error(), testCase.expectedError)1470 }1471 })1472 }1473 t.Run("custom set header", func(t *testing.T) {1474 expectedEncoding = "not, valid"1475 actualEncoding = "gzip, deflate"1476 observedLogs.TakeAll()1477 t.Run("encoding", func(t *testing.T) {1478 _, err := runES6String(t, ctx, rt, tb.Replacer.Replace(`1479 http.post("HTTPBIN_URL/compressed-text", `+"`"+text+"`"+`,1480 {"compression": "`+actualEncoding+`",1481 "headers": {"Content-Encoding": "`+expectedEncoding+`"}1482 }1483 );1484 `))1485 require.NoError(t, err)1486 require.NotEmpty(t, observedLogs.TakeAll())1487 })1488 t.Run("encoding and length", func(t *testing.T) {1489 _, err := runES6String(t, ctx, rt, tb.Replacer.Replace(`1490 http.post("HTTPBIN_URL/compressed-text", `+"`"+text+"`"+`,1491 {"compression": "`+actualEncoding+`",1492 "headers": {"Content-Encoding": "`+expectedEncoding+`",1493 "Content-Length": "12"}1494 }1495 );1496 `))1497 require.NoError(t, err)1498 require.NotEmpty(t, observedLogs.TakeAll())1499 })1500 expectedEncoding = actualEncoding1501 t.Run("correct encoding", func(t *testing.T) {1502 _, err := runES6String(t, ctx, rt, tb.Replacer.Replace(`1503 http.post("HTTPBIN_URL/compressed-text", `+"`"+text+"`"+`,1504 {"compression": "`+actualEncoding+`",1505 "headers": {"Content-Encoding": "`+actualEncoding+`"}1506 }1507 );1508 `))1509 require.NoError(t, err)1510 require.Empty(t, observedLogs.TakeAll())1511 })1512 // TODO: move to some other test?1513 t.Run("correct length", func(t *testing.T) {1514 _, err := rt.RunString(ctx, tb.Replacer.Replace(1515 `http.post("HTTPBIN_URL/post", "0123456789", { "headers": {"Content-Length": "10"}});`,1516 ))1517 require.NoError(t, err)1518 require.Empty(t, observedLogs.TakeAll())1519 })1520 t.Run("content-length is set", func(t *testing.T) {1521 _, err := rt.RunString(ctx, tb.Replacer.Replace(`1522 var resp = http.post("HTTPBIN_URL/post", "0123456789");1523 if (resp.json().headers["Content-Length"][0] != "10") {1524 throw new Error("content-length not set: " + JSON.stringify(resp.json().headers));1525 }1526 `))1527 require.NoError(t, err)1528 require.Empty(t, observedLogs.TakeAll())1529 })1530 })1531}1532func TestResponseTypes(t *testing.T) {1533 t.Parallel()1534 tb, state, _, rt, ctx := newRuntime(t)1535 defer tb.Cleanup()1536 // We don't expect any failed requests1537 state.Options.Throw = null.BoolFrom(true)1538 text := `•?((¯°·._.• ţ€$ţɨɲǥ µɲɨȼ๏ď€ ɨɲ Ќ6 •._.·°¯))؟•`1539 textLen := len(text)1540 tb.Mux.HandleFunc("/get-text", http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {1541 n, err := w.Write([]byte(text))1542 assert.NoError(t, err)1543 assert.Equal(t, textLen, n)1544 }))1545 tb.Mux.HandleFunc("/compare-text", http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {1546 body, err := ioutil.ReadAll(r.Body)1547 require.NoError(t, err)1548 assert.Equal(t, text, string(body))1549 }))1550 binaryLen := 3001551 binary := make([]byte, binaryLen)1552 for i := 0; i < binaryLen; i++ {1553 binary[i] = byte(i)1554 }1555 tb.Mux.HandleFunc("/get-bin", http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {1556 n, err := w.Write(binary)1557 assert.NoError(t, err)1558 assert.Equal(t, binaryLen, n)1559 }))1560 tb.Mux.HandleFunc("/compare-bin", http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {1561 body, err := ioutil.ReadAll(r.Body)1562 require.NoError(t, err)1563 assert.True(t, bytes.Equal(binary, body))1564 }))1565 replace := func(s string) string {1566 return strings.NewReplacer(1567 "EXP_TEXT", text,1568 "EXP_BIN_LEN", strconv.Itoa(binaryLen),1569 ).Replace(tb.Replacer.Replace(s))1570 }1571 _, err := rt.RunString(ctx, replace(`1572 var expText = "EXP_TEXT";1573 var expBinLength = EXP_BIN_LEN;1574 // Check default behaviour with a unicode text1575 var respTextImplicit = http.get("HTTPBIN_URL/get-text").body;1576 if (respTextImplicit !== expText) {1577 throw new Error("default response body should be '" + expText + "' but was '" + respTextImplicit + "'");1578 }1579 http.post("HTTPBIN_URL/compare-text", respTextImplicit);1580 // Check discarding of responses1581 var respNone = http.get("HTTPBIN_URL/get-text", { responseType: "none" }).body;1582 if (respNone != null) {1583 throw new Error("none response body should be null but was " + respNone);1584 }1585 // Check binary transmission of the text response as well1586 var respTextInBin = http.get("HTTPBIN_URL/get-text", { responseType: "binary" }).body;1587 // Hack to convert a utf-8 array to a JS string1588 var strConv = "";1589 function pad(n) { return n.length < 2 ? "0" + n : n; }1590 for( var i = 0; i < respTextInBin.length; i++ ) {1591 strConv += ( "%" + pad(respTextInBin[i].toString(16)));1592 }1593 strConv = decodeURIComponent(strConv);1594 if (strConv !== expText) {1595 throw new Error("converted response body should be '" + expText + "' but was '" + strConv + "'");1596 }1597 http.post("HTTPBIN_URL/compare-text", respTextInBin);1598 // Check binary response1599 var respBin = http.get("HTTPBIN_URL/get-bin", { responseType: "binary" }).body;1600 if (respBin.length !== expBinLength) {1601 throw new Error("response body length should be '" + expBinLength + "' but was '" + respBin.length + "'");1602 }1603 for( var i = 0; i < respBin.length; i++ ) {1604 if ( respBin[i] !== i%256 ) {1605 throw new Error("expected value " + (i%256) + " to be at position " + i + " but it was " + respBin[i]);1606 }1607 }1608 http.post("HTTPBIN_URL/compare-bin", respBin);1609 `))1610 assert.NoError(t, err)1611 // Verify that if we enable discardResponseBodies globally, the default value is none1612 state.Options.DiscardResponseBodies = null.BoolFrom(true)1613 _, err = rt.RunString(ctx, replace(`1614 var expText = "EXP_TEXT";1615 // Check default behaviour1616 var respDefault = http.get("HTTPBIN_URL/get-text").body;1617 if (respDefault !== null) {1618 throw new Error("default response body should be discarded and null but was " + respDefault);1619 }1620 // Check explicit text response1621 var respTextExplicit = http.get("HTTPBIN_URL/get-text", { responseType: "text" }).body;1622 if (respTextExplicit !== expText) {1623 throw new Error("text response body should be '" + expText + "' but was '" + respTextExplicit + "'");1624 }1625 http.post("HTTPBIN_URL/compare-text", respTextExplicit);1626 `))1627 assert.NoError(t, err)1628}1629func checkErrorCode(t testing.TB, tags *stats.SampleTags, code int, msg string) {1630 errorMsg, ok := tags.Get("error")1631 if msg == "" {1632 assert.False(t, ok)1633 } else {1634 assert.Contains(t, errorMsg, msg)1635 }1636 errorCodeStr, ok := tags.Get("error_code")1637 if code == 0 {1638 assert.False(t, ok)1639 } else {1640 errorCode, err := strconv.Atoi(errorCodeStr)1641 assert.NoError(t, err)1642 assert.Equal(t, code, errorCode)1643 }1644}1645func TestErrorCodes(t *testing.T) {1646 t.Parallel()1647 tb, state, samples, rt, ctx := newRuntime(t)1648 state.Options.Throw = null.BoolFrom(false)1649 defer tb.Cleanup()1650 sr := tb.Replacer.Replace1651 // Handple paths with custom logic1652 tb.Mux.HandleFunc("/no-location-redirect", http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) {1653 w.WriteHeader(302)1654 }))1655 tb.Mux.HandleFunc("/bad-location-redirect", http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) {1656 w.Header().Set("Location", "h\t:/") // \n is forbidden1657 w.WriteHeader(302)1658 }))1659 connectionRefusedRedirectMsg := `dial: connection refused`1660 connectionRefusedRedirectCode := 12121661 if runtime.GOOS == "windows" {1662 connectionRefusedRedirectMsg = `dial: i/o timeout`1663 connectionRefusedRedirectCode = 12111664 }1665 testCases := []struct {1666 name string1667 status int1668 moreSamples int1669 expectedErrorCode int1670 expectedErrorMsg string1671 expectedScriptError string1672 script string1673 }{1674 {1675 name: "Unroutable",1676 expectedErrorCode: 1101,1677 expectedErrorMsg: "lookup: no such host",1678 script: `var res = http.request("GET", "http://sdafsgdhfjg.com/");`,1679 },1680 {1681 name: "404",1682 status: 404,1683 expectedErrorCode: 1404,1684 script: `var res = http.request("GET", "HTTPBIN_URL/status/404");`,1685 },1686 {1687 name: "Unroutable redirect",1688 expectedErrorCode: 1101,1689 expectedErrorMsg: "lookup: no such host",1690 moreSamples: 1,1691 script: `var res = http.request("GET", "HTTPBIN_URL/redirect-to?url=http://dafsgdhfjg.com/");`,1692 },1693 {1694 name: "Non location redirect",1695 expectedErrorCode: 1000,1696 expectedErrorMsg: "302 response missing Location header",1697 script: `var res = http.request("GET", "HTTPBIN_URL/no-location-redirect");`,1698 },1699 {1700 name: "Bad location redirect",1701 expectedErrorCode: 1000,1702 expectedErrorMsg: "failed to parse Location header \"h\\t:/\": ",1703 script: `var res = http.request("GET", "HTTPBIN_URL/bad-location-redirect");`,1704 },1705 {1706 name: "Missing protocol",1707 expectedErrorCode: 1000,1708 expectedErrorMsg: `unsupported protocol scheme ""`,1709 script: `var res = http.request("GET", "dafsgdhfjg.com/");`,1710 },1711 {1712 name: "Too many redirects",1713 status: 302,1714 moreSamples: 2,1715 script: `1716 var res = http.get("HTTPBIN_URL/relative-redirect/3", {redirects: 2});1717 if (res.url != "HTTPBIN_URL/relative-redirect/1") { throw new Error("incorrect URL: " + res.url) }`,1718 },1719 {1720 name: "Connection refused redirect",1721 status: 0,1722 moreSamples: 1,1723 expectedErrorMsg: connectionRefusedRedirectMsg,1724 expectedErrorCode: connectionRefusedRedirectCode,1725 script: `1726 var res = http.get("HTTPBIN_URL/redirect-to?url=http%3A%2F%2F127.0.0.1%3A1%2Fpesho");1727 if (res.url != "http://127.0.0.1:1/pesho") { throw new Error("incorrect URL: " + res.url) }`,1728 },1729 }1730 for _, testCase := range testCases {1731 testCase := testCase1732 // clear the Samples1733 stats.GetBufferedSamples(samples)1734 t.Run(testCase.name, func(t *testing.T) {1735 _, err := rt.RunString(ctx,1736 sr(testCase.script+"\n"+fmt.Sprintf(`1737 if (res.status != %d) { throw new Error("wrong status: "+ res.status);}1738 if (res.error.indexOf(%q, 0) === -1) { throw new Error("wrong error: '" + res.error + "'");}1739 if (res.error_code != %d) { throw new Error("wrong error_code: "+ res.error_code);}1740 `, testCase.status, testCase.expectedErrorMsg, testCase.expectedErrorCode)))1741 if testCase.expectedScriptError == "" {1742 require.NoError(t, err)1743 } else {1744 require.Error(t, err)1745 require.Equal(t, err.Error(), testCase.expectedScriptError)1746 }1747 cs := stats.GetBufferedSamples(samples)1748 assert.Len(t, cs, 1+testCase.moreSamples)1749 for _, c := range cs[len(cs)-1:] {1750 assert.NotZero(t, len(c.GetSamples()))1751 for _, sample := range c.GetSamples() {1752 checkErrorCode(t, sample.GetTags(), testCase.expectedErrorCode, testCase.expectedErrorMsg)1753 }1754 }1755 })1756 }1757}1758func TestResponseWaitingAndReceivingTimings(t *testing.T) {1759 t.Parallel()1760 tb, state, _, rt, ctx := newRuntime(t)1761 defer tb.Cleanup()1762 // We don't expect any failed requests1763 state.Options.Throw = null.BoolFrom(true)1764 tb.Mux.HandleFunc("/slow-response", http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {1765 flusher, ok := w.(http.Flusher)1766 require.True(t, ok)1767 time.Sleep(1200 * time.Millisecond)1768 n, err := w.Write([]byte("1st bytes!"))1769 assert.NoError(t, err)1770 assert.Equal(t, 10, n)1771 flusher.Flush()1772 time.Sleep(1200 * time.Millisecond)1773 n, err = w.Write([]byte("2nd bytes!"))1774 assert.NoError(t, err)1775 assert.Equal(t, 10, n)1776 }))1777 _, err := rt.RunString(ctx, tb.Replacer.Replace(`1778 var resp = http.get("HTTPBIN_URL/slow-response");1779 if (resp.timings.waiting < 1000) {1780 throw new Error("expected waiting time to be over 1000ms but was " + resp.timings.waiting);1781 }1782 if (resp.timings.receiving < 1000) {1783 throw new Error("expected receiving time to be over 1000ms but was " + resp.timings.receiving);1784 }1785 if (resp.body !== "1st bytes!2nd bytes!") {1786 throw new Error("wrong response body: " + resp.body);1787 }1788 `))1789 assert.NoError(t, err)1790}1791func TestResponseTimingsWhenTimeout(t *testing.T) {1792 t.Parallel()1793 tb, state, _, rt, ctx := newRuntime(t)1794 defer tb.Cleanup()1795 // We expect a failed request1796 state.Options.Throw = null.BoolFrom(false)1797 _, err := rt.RunString(ctx, tb.Replacer.Replace(`1798 var resp = http.get("HTTPBIN_URL/delay/10", { timeout: 2500 });1799 if (resp.timings.waiting < 2000) {1800 throw new Error("expected waiting time to be over 2000ms but was " + resp.timings.waiting);1801 }1802 if (resp.timings.duration < 2000) {1803 throw new Error("expected duration time to be over 2000ms but was " + resp.timings.duration);1804 }1805 `))1806 assert.NoError(t, err)1807}1808func TestNoResponseBodyMangling(t *testing.T) {1809 t.Parallel()1810 tb, state, _, rt, ctx := newRuntime(t)1811 defer tb.Cleanup()1812 // We don't expect any failed requests1813 state.Options.Throw = null.BoolFrom(true)1814 _, err := rt.RunString(ctx, tb.Replacer.Replace(`1815 var batchSize = 100;1816 var requests = [];1817 for (var i = 0; i < batchSize; i++) {1818 requests.push(["GET", "HTTPBIN_URL/get?req=" + i, null, { responseType: (i % 2 ? "binary" : "text") }]);1819 }1820 var responses = http.batch(requests);1821 for (var i = 0; i < batchSize; i++) {1822 var reqNumber = parseInt(responses[i].json().args.req[0], 10);1823 if (i !== reqNumber) {1824 throw new Error("Response " + i + " has " + reqNumber + ", expected " + i)1825 }1826 }1827 `))1828 assert.NoError(t, err)1829}1830func TestRedirectMetricTags(t *testing.T) {1831 tb, _, samples, rt, ctx := newRuntime(t)1832 defer tb.Cleanup()1833 tb.Mux.HandleFunc("/redirect/post", http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {1834 http.Redirect(w, r, "/get", http.StatusMovedPermanently)1835 }))1836 sr := tb.Replacer.Replace1837 script := sr(`1838 http.post("HTTPBIN_URL/redirect/post", {data: "some data"});1839 `)1840 _, err := rt.RunString(ctx, script)1841 require.NoError(t, err)1842 require.Len(t, samples, 2)1843 checkTags := func(sc stats.SampleContainer, expTags map[string]string) {1844 allSamples := sc.GetSamples()1845 assert.Len(t, allSamples, 8)1846 for _, s := range allSamples {1847 assert.Equal(t, expTags, s.Tags.CloneTags())1848 }1849 }1850 expPOSTtags := map[string]string{1851 "group": "",1852 "method": "POST",1853 "url": sr("HTTPBIN_URL/redirect/post"),1854 "name": sr("HTTPBIN_URL/redirect/post"),1855 "status": "301",1856 "proto": "HTTP/1.1",1857 }1858 expGETtags := map[string]string{1859 "group": "",1860 "method": "GET",1861 "url": sr("HTTPBIN_URL/get"),1862 "name": sr("HTTPBIN_URL/get"),1863 "status": "200",1864 "proto": "HTTP/1.1",1865 }1866 checkTags(<-samples, expPOSTtags)1867 checkTags(<-samples, expGETtags)1868}1869func BenchmarkHandlingOfResponseBodies(b *testing.B) {1870 tb, state, samples, rt, ctx := newRuntime(b)1871 defer tb.Cleanup()1872 state.BPool = bpool.NewBufferPool(100)1873 go func() {1874 ctxDone := tb.Context.Done()1875 for {1876 select {1877 case <-samples:1878 case <-ctxDone:1879 return1880 }1881 }1882 }()1883 mbData := bytes.Repeat([]byte("0123456789"), 100000)1884 tb.Mux.HandleFunc("/1mbdata", http.HandlerFunc(func(resp http.ResponseWriter, req *http.Request) {1885 _, err := resp.Write(mbData)1886 if err != nil {1887 b.Error(err)1888 }1889 }))1890 testCodeTemplate := tb.Replacer.Replace(`1891 http.get("HTTPBIN_URL/", { responseType: "TEST_RESPONSE_TYPE" });1892 http.post("HTTPBIN_URL/post", { responseType: "TEST_RESPONSE_TYPE" });1893 http.batch([1894 ["GET", "HTTPBIN_URL/gzip", null, { responseType: "TEST_RESPONSE_TYPE" }],1895 ["GET", "HTTPBIN_URL/gzip", null, { responseType: "TEST_RESPONSE_TYPE" }],1896 ["GET", "HTTPBIN_URL/deflate", null, { responseType: "TEST_RESPONSE_TYPE" }],1897 ["GET", "HTTPBIN_URL/deflate", null, { responseType: "TEST_RESPONSE_TYPE" }],1898 ["GET", "HTTPBIN_URL/redirect/5", null, { responseType: "TEST_RESPONSE_TYPE" }], // 6 requests1899 ["GET", "HTTPBIN_URL/get", null, { responseType: "TEST_RESPONSE_TYPE" }],1900 ["GET", "HTTPBIN_URL/html", null, { responseType: "TEST_RESPONSE_TYPE" }],1901 ["GET", "HTTPBIN_URL/bytes/100000", null, { responseType: "TEST_RESPONSE_TYPE" }],1902 ["GET", "HTTPBIN_URL/image/png", null, { responseType: "TEST_RESPONSE_TYPE" }],1903 ["GET", "HTTPBIN_URL/image/jpeg", null, { responseType: "TEST_RESPONSE_TYPE" }],1904 ["GET", "HTTPBIN_URL/image/jpeg", null, { responseType: "TEST_RESPONSE_TYPE" }],1905 ["GET", "HTTPBIN_URL/image/webp", null, { responseType: "TEST_RESPONSE_TYPE" }],1906 ["GET", "HTTPBIN_URL/image/svg", null, { responseType: "TEST_RESPONSE_TYPE" }],1907 ["GET", "HTTPBIN_URL/forms/post", null, { responseType: "TEST_RESPONSE_TYPE" }],1908 ["GET", "HTTPBIN_URL/bytes/100000", null, { responseType: "TEST_RESPONSE_TYPE" }],1909 ["GET", "HTTPBIN_URL/stream-bytes/100000", null, { responseType: "TEST_RESPONSE_TYPE" }],1910 ]);1911 http.get("HTTPBIN_URL/get", { responseType: "TEST_RESPONSE_TYPE" });1912 http.get("HTTPBIN_URL/get", { responseType: "TEST_RESPONSE_TYPE" });1913 http.get("HTTPBIN_URL/1mbdata", { responseType: "TEST_RESPONSE_TYPE" });1914 `)1915 testResponseType := func(responseType string) func(b *testing.B) {1916 testCode := strings.Replace(testCodeTemplate, "TEST_RESPONSE_TYPE", responseType, -1)1917 return func(b *testing.B) {1918 for i := 0; i < b.N; i++ {1919 _, err := rt.RunString(ctx, testCode)1920 if err != nil {1921 b.Error(err)1922 }1923 }1924 }1925 }1926 b.ResetTimer()1927 b.Run("text", testResponseType("text"))1928 b.Run("binary", testResponseType("binary"))1929 b.Run("none", testResponseType("none"))1930}1931func TestErrorsWithDecompression(t *testing.T) {1932 t.Parallel()1933 tb, state, _, rt, ctx := newRuntime(t)1934 defer tb.Cleanup()1935 state.Options.Throw = null.BoolFrom(false)1936 tb.Mux.HandleFunc("/broken-archive", http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {1937 enc := r.URL.Query()["encoding"][0]1938 w.Header().Set("Content-Encoding", enc)1939 _, _ = fmt.Fprintf(w, "Definitely not %s, but it's all cool...", enc)1940 }))1941 _, err := rt.RunString(ctx, tb.Replacer.Replace(`1942 function handleResponseEncodingError (encoding) {1943 var resp = http.get("HTTPBIN_URL/broken-archive?encoding=" + encoding);1944 if (resp.error_code != 1701) {1945 throw new Error("Expected error_code 1701 for '" + encoding +"', but got " + resp.error_code);1946 }1947 }1948 ["gzip", "deflate", "br", "zstd"].forEach(handleResponseEncodingError);1949 `))1950 assert.NoError(t, err)1951}1952func TestDigestAuthWithBody(t *testing.T) {1953 t.Parallel()1954 tb, state, samples, rt, ctx := newRuntime(t)1955 defer tb.Cleanup()1956 state.Options.Throw = null.BoolFrom(true)1957 state.Options.HTTPDebug = null.StringFrom("full")1958 tb.Mux.HandleFunc("/digest-auth-with-post/", http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {1959 require.Equal(t, "POST", r.Method)1960 body, err := ioutil.ReadAll(r.Body)1961 require.NoError(t, err)1962 require.Equal(t, "super secret body", string(body))1963 httpbin.New().DigestAuth(w, r) // this doesn't read the body1964 }))1965 urlWithCreds := tb.Replacer.Replace(1966 "http://testuser:testpwd@HTTPBIN_IP:HTTPBIN_PORT/digest-auth-with-post/auth/testuser/testpwd",1967 )1968 _, err := rt.RunString(ctx, fmt.Sprintf(`1969 var res = http.post(%q, "super secret body", { auth: "digest" });1970 if (res.status !== 200) { throw new Error("wrong status: " + res.status); }1971 if (res.error_code !== 0) { throw new Error("wrong error code: " + res.error_code); }1972 `, urlWithCreds))1973 require.NoError(t, err)1974 urlRaw := tb.Replacer.Replace(1975 "http://HTTPBIN_IP:HTTPBIN_PORT/digest-auth-with-post/auth/testuser/testpwd")1976 sampleContainers := stats.GetBufferedSamples(samples)1977 assertRequestMetricsEmitted(t, sampleContainers[0:1], "POST", urlRaw, urlRaw, 401, "")1978 assertRequestMetricsEmitted(t, sampleContainers[1:2], "POST", urlRaw, urlRaw, 200, "")1979}...

Full Screen

Full Screen

ws_test.go

Source:ws_test.go Github

copy

Full Screen

...114 if (res.status != 101) { throw new Error("connection failed with status: " + res.status); }115 `))116 assert.NoError(t, err)117 })118 assertSessionMetricsEmitted(t, stats.GetBufferedSamples(samples), "", sr("WSBIN_URL/ws-echo"), 101, "")119 t.Run("connect_wss", func(t *testing.T) {120 _, err := rt.RunString(ctx, sr(`121 var res = ws.connect("WSSBIN_URL/ws-echo", function(socket){122 socket.close()123 });124 if (res.status != 101) { throw new Error("TLS connection failed with status: " + res.status); }125 `))126 assert.NoError(t, err)127 })128 assertSessionMetricsEmitted(t, stats.GetBufferedSamples(samples), "", sr("WSSBIN_URL/ws-echo"), 101, "")129 t.Run("open", func(t *testing.T) {130 _, err := rt.RunString(ctx, sr(`131 var opened = false;132 var res = ws.connect("WSBIN_URL/ws-echo", function(socket){133 socket.on("open", function() {134 opened = true;135 socket.close()136 })137 });138 if (!opened) { throw new Error ("open event not fired"); }139 `))140 assert.NoError(t, err)141 })142 assertSessionMetricsEmitted(t, stats.GetBufferedSamples(samples), "", sr("WSBIN_URL/ws-echo"), 101, "")143 t.Run("send_receive", func(t *testing.T) {144 _, err := rt.RunString(ctx, sr(`145 var res = ws.connect("WSBIN_URL/ws-echo", function(socket){146 socket.on("open", function() {147 socket.send("test")148 })149 socket.on("message", function (data){150 if (!data=="test") {151 throw new Error ("echo'd data doesn't match our message!");152 }153 socket.close()154 });155 });156 `))157 assert.NoError(t, err)158 })159 samplesBuf := stats.GetBufferedSamples(samples)160 assertSessionMetricsEmitted(t, samplesBuf, "", sr("WSBIN_URL/ws-echo"), 101, "")161 assertMetricEmitted(t, metrics.WSMessagesSent, samplesBuf, sr("WSBIN_URL/ws-echo"))162 assertMetricEmitted(t, metrics.WSMessagesReceived, samplesBuf, sr("WSBIN_URL/ws-echo"))163 t.Run("interval", func(t *testing.T) {164 _, err := rt.RunString(ctx, sr(`165 var counter = 0;166 var res = ws.connect("WSBIN_URL/ws-echo", function(socket){167 socket.setInterval(function () {168 counter += 1;169 if (counter > 2) { socket.close(); }170 }, 100);171 });172 if (counter < 3) {throw new Error ("setInterval should have been called at least 3 times, counter=" + counter);}173 `))174 assert.NoError(t, err)175 })176 assertSessionMetricsEmitted(t, stats.GetBufferedSamples(samples), "", sr("WSBIN_URL/ws-echo"), 101, "")177 t.Run("bad interval", func(t *testing.T) {178 _, err := rt.RunString(ctx, sr(`179 var counter = 0;180 var res = ws.connect("WSBIN_URL/ws-echo", function(socket){181 socket.setInterval(function () {182 counter += 1;183 if (counter > 2) { socket.close(); }184 }, -1.23);185 });186 `))187 require.Error(t, err)188 require.Contains(t, err.Error(), "setInterval requires a >0 timeout parameter, received -1.23 ")189 })190 t.Run("timeout", func(t *testing.T) {191 _, err := rt.RunString(ctx, sr(`192 var start = new Date().getTime();193 var ellapsed = new Date().getTime() - start;194 var res = ws.connect("WSBIN_URL/ws-echo", function(socket){195 socket.setTimeout(function () {196 ellapsed = new Date().getTime() - start;197 socket.close();198 }, 500);199 });200 if (ellapsed > 3000 || ellapsed < 500) {201 throw new Error ("setTimeout occurred after " + ellapsed + "ms, expected 500<T<3000");202 }203 `))204 assert.NoError(t, err)205 })206 t.Run("bad timeout", func(t *testing.T) {207 _, err := rt.RunString(ctx, sr(`208 var start = new Date().getTime();209 var ellapsed = new Date().getTime() - start;210 var res = ws.connect("WSBIN_URL/ws-echo", function(socket){211 socket.setTimeout(function () {212 ellapsed = new Date().getTime() - start;213 socket.close();214 }, 0);215 });216 `))217 require.Error(t, err)218 require.Contains(t, err.Error(), "setTimeout requires a >0 timeout parameter, received 0.00 ")219 })220 assertSessionMetricsEmitted(t, stats.GetBufferedSamples(samples), "", sr("WSBIN_URL/ws-echo"), 101, "")221 t.Run("ping", func(t *testing.T) {222 _, err := rt.RunString(ctx, sr(`223 var pongReceived = false;224 var res = ws.connect("WSBIN_URL/ws-echo", function(socket){225 socket.on("open", function(data) {226 socket.ping();227 });228 socket.on("pong", function() {229 pongReceived = true;230 socket.close();231 });232 socket.setTimeout(function (){socket.close();}, 3000);233 });234 if (!pongReceived) {235 throw new Error ("sent ping but didn't get pong back");236 }237 `))238 assert.NoError(t, err)239 })240 samplesBuf = stats.GetBufferedSamples(samples)241 assertSessionMetricsEmitted(t, samplesBuf, "", sr("WSBIN_URL/ws-echo"), 101, "")242 assertMetricEmitted(t, metrics.WSPing, samplesBuf, sr("WSBIN_URL/ws-echo"))243 t.Run("multiple_handlers", func(t *testing.T) {244 _, err := rt.RunString(ctx, sr(`245 var pongReceived = false;246 var otherPongReceived = false;247 var res = ws.connect("WSBIN_URL/ws-echo", function(socket){248 socket.on("open", function(data) {249 socket.ping();250 });251 socket.on("pong", function() {252 pongReceived = true;253 if (otherPongReceived) {254 socket.close();255 }256 });257 socket.on("pong", function() {258 otherPongReceived = true;259 if (pongReceived) {260 socket.close();261 }262 });263 socket.setTimeout(function (){socket.close();}, 3000);264 });265 if (!pongReceived || !otherPongReceived) {266 throw new Error ("sent ping but didn't get pong back");267 }268 `))269 assert.NoError(t, err)270 })271 samplesBuf = stats.GetBufferedSamples(samples)272 assertSessionMetricsEmitted(t, samplesBuf, "", sr("WSBIN_URL/ws-echo"), 101, "")273 assertMetricEmitted(t, metrics.WSPing, samplesBuf, sr("WSBIN_URL/ws-echo"))274 t.Run("client_close", func(t *testing.T) {275 _, err := rt.RunString(ctx, sr(`276 var closed = false;277 var res = ws.connect("WSBIN_URL/ws-echo", function(socket){278 socket.on("open", function() {279 socket.close()280 })281 socket.on("close", function() {282 closed = true;283 })284 });285 if (!closed) { throw new Error ("close event not fired"); }286 `))287 assert.NoError(t, err)288 })289 assertSessionMetricsEmitted(t, stats.GetBufferedSamples(samples), "", sr("WSBIN_URL/ws-echo"), 101, "")290 serverCloseTests := []struct {291 name string292 endpoint string293 }{294 {"server_close_ok", "/ws-echo"},295 // Ensure we correctly handle invalid WS server296 // implementations that close the connection prematurely297 // without sending a close control frame first.298 {"server_close_invalid", "/ws-close-invalid"},299 }300 for _, tc := range serverCloseTests {301 tc := tc302 t.Run(tc.name, func(t *testing.T) {303 _, err := rt.RunString(ctx, sr(fmt.Sprintf(`304 var closed = false;305 var res = ws.connect("WSBIN_URL%s", function(socket){306 socket.on("open", function() {307 socket.send("test");308 })309 socket.on("close", function() {310 closed = true;311 })312 });313 if (!closed) { throw new Error ("close event not fired"); }314 `, tc.endpoint)))315 assert.NoError(t, err)316 })317 }318}319func TestErrors(t *testing.T) {320 t.Parallel()321 tb := httpmultibin.NewHTTPMultiBin(t)322 defer tb.Cleanup()323 sr := tb.Replacer.Replace324 // root, err := lib.NewGroup("", nil)325 // assert.NoError(t, err)326 rt := gojs.New()327 rt.SetFieldNameMapper(gojs.FieldNameMapper{})328 samples := make(chan stats.SampleContainer, 1000)329 state := &lib.State{330 // Group: root,331 Dialer: tb.Dialer,332 Options: lib.Options{333 SystemTags: &stats.DefaultSystemTagSet,334 },335 Samples: samples,336 }337 ctx := context.Background()338 ctx = lib.WithState(ctx, state)339 ctx = gojs.WithRuntime(ctx, rt)340 rt.Bind("ws", New())341 t.Run("invalid_url", func(t *testing.T) {342 _, err := rt.RunString(ctx, `343 var res = ws.connect("INVALID", function(socket){344 socket.on("open", function() {345 socket.close();346 });347 });348 `)349 assert.Error(t, err)350 })351 t.Run("invalid_url_message_panic", func(t *testing.T) {352 // Attempting to send a message to a non-existent socket shouldn't panic353 _, err := rt.RunString(ctx, `354 var res = ws.connect("INVALID", function(socket){355 socket.send("new message");356 });357 `)358 assert.Error(t, err)359 })360 t.Run("error_in_setup", func(t *testing.T) {361 _, err := rt.RunString(ctx, sr(`362 var res = ws.connect("WSBIN_URL/ws-echo-invalid", function(socket){363 throw new Error("error in setup");364 });365 `))366 assert.Error(t, err)367 })368 t.Run("send_after_close", func(t *testing.T) {369 _, err := rt.RunString(ctx, sr(`370 var hasError = false;371 var res = ws.connect("WSBIN_URL/ws-echo-invalid", function(socket){372 socket.on("open", function() {373 socket.close();374 socket.send("test");375 });376 socket.on("error", function(errorEvent) {377 hasError = true;378 });379 });380 if (!hasError) {381 throw new Error ("no error emitted for send after close");382 }383 `))384 assert.NoError(t, err)385 assertSessionMetricsEmitted(t, stats.GetBufferedSamples(samples), "", sr("WSBIN_URL/ws-echo-invalid"), 101, "")386 })387 t.Run("error on close", func(t *testing.T) {388 _, err := rt.RunString(ctx, sr(`389 var closed = false;390 var res = ws.connect("WSBIN_URL/ws-close", function(socket){391 socket.on('open', function open() {392 socket.setInterval(function timeout() {393 socket.ping();394 }, 1000);395 });396 socket.on("ping", function() {397 socket.close();398 });399 socket.on("error", function(errorEvent) {400 if (errorEvent == null) {401 throw new Error(JSON.stringify(errorEvent));402 }403 if (!closed) {404 closed = true;405 socket.close();406 }407 });408 });409 `))410 assert.NoError(t, err)411 assertSessionMetricsEmitted(t, stats.GetBufferedSamples(samples), "", sr("WSBIN_URL/ws-close"), 101, "")412 })413}414func TestSystemTags(t *testing.T) {415 tb := httpmultibin.NewHTTPMultiBin(t)416 defer tb.Cleanup()417 sr := tb.Replacer.Replace418 // root, err := lib.NewGroup("", nil)419 // assert.NoError(t, err)420 rt := gojs.New()421 rt.SetFieldNameMapper(gojs.FieldNameMapper{})422 // TODO: test for actual tag values after removing the dependency on the423 // external service demos.kaazing.com (https://github.com/loadimpact/k6/issues/537)424 testedSystemTags := []string{"group", "status", "subproto", "url", "ip"}425 samples := make(chan stats.SampleContainer, 1000)426 state := &lib.State{427 // Group: root,428 Dialer: tb.Dialer,429 Options: lib.Options{SystemTags: stats.ToSystemTagSet(testedSystemTags)},430 Samples: samples,431 TLSConfig: tb.TLSClientConfig,432 }433 ctx := context.Background()434 ctx = lib.WithState(ctx, state)435 ctx = gojs.WithRuntime(ctx, rt)436 rt.Bind("ws", New())437 for _, expectedTag := range testedSystemTags {438 expectedTag := expectedTag439 t.Run("only "+expectedTag, func(t *testing.T) {440 state.Options.SystemTags = stats.ToSystemTagSet([]string{expectedTag})441 _, err := rt.RunString(ctx, sr(`442 var res = ws.connect("WSBIN_URL/ws-echo", function(socket){443 socket.on("open", function() {444 socket.send("test")445 })446 socket.on("message", function (data){447 if (!data=="test") {448 throw new Error ("echo'd data doesn't match our message!");449 }450 socket.close()451 });452 });453 `))454 assert.NoError(t, err)455 for _, sampleContainer := range stats.GetBufferedSamples(samples) {456 for _, sample := range sampleContainer.GetSamples() {457 for emittedTag := range sample.Tags.CloneTags() {458 assert.Equal(t, expectedTag, emittedTag)459 }460 }461 }462 })463 }464}465func TestTLSConfig(t *testing.T) {466 // root, err := lib.NewGroup("", nil)467 // assert.NoError(t, err)468 tb := httpmultibin.NewHTTPMultiBin(t)469 defer tb.Cleanup()470 sr := tb.Replacer.Replace471 rt := gojs.New()472 rt.SetFieldNameMapper(gojs.FieldNameMapper{})473 samples := make(chan stats.SampleContainer, 1000)474 state := &lib.State{475 // Group: root,476 Dialer: tb.Dialer,477 Options: lib.Options{478 SystemTags: stats.NewSystemTagSet(479 stats.TagURL,480 stats.TagProto,481 stats.TagStatus,482 stats.TagSubproto,483 stats.TagIP,484 ),485 },486 Samples: samples,487 }488 ctx := context.Background()489 ctx = lib.WithState(ctx, state)490 ctx = gojs.WithRuntime(ctx, rt)491 rt.Bind("ws", New())492 t.Run("insecure skip verify", func(t *testing.T) {493 state.TLSConfig = &tls.Config{494 InsecureSkipVerify: true,495 }496 _, err := rt.RunString(ctx, sr(`497 var res = ws.connect("WSSBIN_URL/ws-close", function(socket){498 socket.close()499 });500 if (res.status != 101) { throw new Error("TLS connection failed with status: " + res.status); }501 `))502 assert.NoError(t, err)503 })504 assertSessionMetricsEmitted(t, stats.GetBufferedSamples(samples), "", sr("WSSBIN_URL/ws-close"), 101, "")505 t.Run("custom certificates", func(t *testing.T) {506 state.TLSConfig = tb.TLSClientConfig507 _, err := rt.RunString(ctx, sr(`508 var res = ws.connect("WSSBIN_URL/ws-close", function(socket){509 socket.close()510 });511 if (res.status != 101) {512 throw new Error("TLS connection failed with status: " + res.status);513 }514 `))515 assert.NoError(t, err)516 })517 assertSessionMetricsEmitted(t, stats.GetBufferedSamples(samples), "", sr("WSSBIN_URL/ws-close"), 101, "")518}519func TestReadPump(t *testing.T) {520 var closeCode int521 srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {522 conn, err := (&websocket.Upgrader{}).Upgrade(w, r, w.Header())523 assert.NoError(t, err)524 closeMsg := websocket.FormatCloseMessage(closeCode, "")525 _ = conn.WriteControl(websocket.CloseMessage, closeMsg, time.Now().Add(time.Second))526 }))527 defer srv.Close()528 closeCodes := []int{websocket.CloseNormalClosure, websocket.CloseGoingAway, websocket.CloseInternalServerErr}529 numAsserts := 0530 srvURL := "ws://" + srv.Listener.Addr().String()531 // Ensure readPump returns the response close code sent by the server...

Full Screen

Full Screen

helpers_test.go

Source:helpers_test.go Github

copy

Full Screen

...39 Tags: metrics.NewSampleTags(map[string]string{"tag1": "val1"}),40 }41 connected := metrics.ConnectedSamples{Samples: []metrics.Sample{single, single}, Time: single.Time}42 buffer := SampleBuffer{}43 assert.Empty(t, buffer.GetBufferedSamples())44 buffer.AddMetricSamples([]metrics.SampleContainer{single, single})45 buffer.AddMetricSamples([]metrics.SampleContainer{single, connected, single})46 assert.Equal(t, []metrics.SampleContainer{single, single, single, connected, single}, buffer.GetBufferedSamples())47 assert.Empty(t, buffer.GetBufferedSamples())48 // Verify some internals49 assert.Equal(t, cap(buffer.buffer), 5)50 buffer.AddMetricSamples([]metrics.SampleContainer{single, connected})51 buffer.AddMetricSamples(nil)52 buffer.AddMetricSamples([]metrics.SampleContainer{})53 buffer.AddMetricSamples([]metrics.SampleContainer{single})54 assert.Equal(t, []metrics.SampleContainer{single, connected, single}, buffer.GetBufferedSamples())55 assert.Equal(t, cap(buffer.buffer), 4)56 buffer.AddMetricSamples([]metrics.SampleContainer{single})57 assert.Equal(t, []metrics.SampleContainer{single}, buffer.GetBufferedSamples())58 assert.Equal(t, cap(buffer.buffer), 3)59 assert.Empty(t, buffer.GetBufferedSamples())60}61func TestSampleBufferConcurrently(t *testing.T) {62 t.Parallel()63 seed := time.Now().UnixNano()64 r := rand.New(rand.NewSource(seed)) //nolint:gosec65 t.Logf("Random source seeded with %d\n", seed)66 registry := metrics.NewRegistry()67 metric, err := registry.NewMetric("my_metric", metrics.Gauge)68 require.NoError(t, err)69 producersCount := 50 + r.Intn(50)70 sampleCount := 10 + r.Intn(10)71 sleepModifier := 10 + r.Intn(10)72 buffer := SampleBuffer{}73 wg := make(chan struct{})74 fillBuffer := func() {75 for i := 0; i < sampleCount; i++ {76 buffer.AddMetricSamples([]metrics.SampleContainer{metrics.Sample{77 Time: time.Unix(1562324644, 0),78 Metric: metric,79 Value: float64(i),80 Tags: metrics.NewSampleTags(map[string]string{"tag1": "val1"}),81 }})82 time.Sleep(time.Duration(i*sleepModifier) * time.Microsecond)83 }84 wg <- struct{}{}85 }86 for i := 0; i < producersCount; i++ {87 go fillBuffer()88 }89 timer := time.NewTicker(5 * time.Millisecond)90 timeout := time.After(5 * time.Second)91 defer timer.Stop()92 readSamples := make([]metrics.SampleContainer, 0, sampleCount*producersCount)93 finishedProducers := 094loop:95 for {96 select {97 case <-timer.C:98 readSamples = append(readSamples, buffer.GetBufferedSamples()...)99 case <-wg:100 finishedProducers++101 if finishedProducers == producersCount {102 readSamples = append(readSamples, buffer.GetBufferedSamples()...)103 break loop104 }105 case <-timeout:106 t.Fatalf("test timed out")107 }108 }109 assert.Equal(t, sampleCount*producersCount, len(readSamples))110 for _, s := range readSamples {111 require.NotNil(t, s)112 ss := s.GetSamples()113 require.Len(t, ss, 1)114 assert.Equal(t, "my_metric", ss[0].Metric.Name)115 }116}...

Full Screen

Full Screen

GetBufferedSamples

Using AI Code Generation

copy

Full Screen

1import (2func main() {3 setting.NewConfigContext(&setting.CommandLineArgs{4 })5 err := util.InitLogger(setting.LogLevel)6 if err != nil {7 log.Fatal(4, "Failed to initialize logger: %s", err)8 }9 if err := services.Init(); err != nil {10 log.Fatal(4, "Failed to initialize service: %s", err)11 }

Full Screen

Full Screen

GetBufferedSamples

Using AI Code Generation

copy

Full Screen

1import (2func main() {3 samples, err := metrics.GetBufferedSamples()4 if err != nil {5 fmt.Println("Error: ", err)6 }7 fmt.Println("Samples: ", samples)8}9import (10func main() {11 samples, err := metrics.GetBufferedSamples()12 if err != nil {13 fmt.Println("Error: ", err)14 }15 fmt.Println("Samples: ", samples)16}17import (18func main() {19 samples, err := metrics.GetBufferedSamples()20 if err != nil {21 fmt.Println("Error: ", err)22 }23 fmt.Println("Samples: ", samples)24}25import (26func main() {27 samples, err := metrics.GetBufferedSamples()28 if err != nil {29 fmt.Println("Error: ", err)30 }31 fmt.Println("Samples: ", samples)32}33import (34func main() {35 samples, err := metrics.GetBufferedSamples()36 if err != nil {37 fmt.Println("Error: ", err)38 }39 fmt.Println("Samples: ", samples)40}41import (

Full Screen

Full Screen

GetBufferedSamples

Using AI Code Generation

copy

Full Screen

1import (2func main() {3 metrics := ebpf.NewMetrics()4 samples, err := metrics.GetBufferedSamples()5 if err != nil {6 fmt.Println(err)7 }8 for _, sample := range samples {9 fmt.Println(sample)10 }11}12{Name:system.net.bytes_rcvd Tags:[host:localhost pid:1] Value:0}13{Name:system.net.bytes_sent Tags:[host:localhost pid:1] Value:0}14{Name:system.net.conn_closed Tags:[host:localhost pid:1] Value:0}15{Name:system.net.conn_opened Tags:[host:localhost pid:1] Value:0}16{Name:system.net.drops Tags:[host:localhost pid:1] Value:0}17{Name:system.net.errors Tags:[host:localhost pid:1] Value:0}18{Name:system.net.packets_in Tags:[host:localhost pid:1] Value:0}19{Name:system.net.packets_out Tags:[host:localhost pid:1] Value:0}20import (21func main() {22 metrics := ebpf.NewMetrics()23 samples, err := metrics.GetBufferedSamples()24 if err != nil {25 fmt.Println(err)26 }27 for _, sample := range samples {28 fmt.Println(sample)29 }30}31{Name:system.net.bytes_rcvd Tags:[host:localhost pid:1] Value:0}32{Name:system.net.bytes_sent Tags:[host:localhost pid:1] Value:0}33{Name:system.net.conn_closed Tags:[host:localhost pid:1] Value:0}34{Name:system.net.conn_opened Tags:[host:localhost pid:1] Value:0}35{Name:system.net.drops Tags:[host:localhost pid:1] Value:0}36{Name:system.net.errors Tags:[host:localhost pid:1] Value:0}37{Name:system.net.packets_in Tags:[host:localhost pid:1] Value:0}38{Name:system.net

Full Screen

Full Screen

GetBufferedSamples

Using AI Code Generation

copy

Full Screen

1import (2func main() {3 m.Init(5)4 m.AddSample(1)5 m.AddSample(2)6 m.AddSample(3)7 m.AddSample(4)8 m.AddSample(5)9 m.AddSample(6)10 m.AddSample(7)11 m.AddSample(8)12 m.AddSample(9)13 m.AddSample(10)14 m.AddSample(11)15 m.AddSample(12)16 m.AddSample(13)17 m.AddSample(14)18 m.AddSample(15)19 m.AddSample(16)20 m.AddSample(17)21 m.AddSample(18)22 m.AddSample(19)23 m.AddSample(20)24 m.AddSample(21)25 m.AddSample(22)26 m.AddSample(23)27 m.AddSample(24)28 m.AddSample(25)29 m.AddSample(26)30 m.AddSample(27)31 m.AddSample(28)32 m.AddSample(29)33 m.AddSample(30)34 m.AddSample(31)35 m.AddSample(32)36 m.AddSample(33)37 m.AddSample(34)38 m.AddSample(35)39 m.AddSample(36)40 m.AddSample(37)41 m.AddSample(38)42 m.AddSample(39)43 m.AddSample(40)44 m.AddSample(41)45 m.AddSample(42)46 m.AddSample(43)47 m.AddSample(44)48 m.AddSample(45)49 m.AddSample(46)50 m.AddSample(47)51 m.AddSample(48)52 m.AddSample(49)53 m.AddSample(50)54 m.AddSample(51)55 m.AddSample(52)56 m.AddSample(53)57 m.AddSample(54)58 m.AddSample(55)59 m.AddSample(56)60 m.AddSample(57)61 m.AddSample(58)62 m.AddSample(59)63 m.AddSample(60)64 m.AddSample(61)65 m.AddSample(62)66 m.AddSample(63)67 m.AddSample(64)68 m.AddSample(65)69 m.AddSample(66)70 m.AddSample(67)

Full Screen

Full Screen

GetBufferedSamples

Using AI Code Generation

copy

Full Screen

1import (2func main() {3 metrics := monitoring.Default.NewRegistry("test")4 numCalls := monitoring.NewInt(metrics, "num_calls")5 totalTime := monitoring.NewInt(metrics, "total_time")6 numErrors := monitoring.NewInt(metrics, "num_errors")7 numSuccess := monitoring.NewInt(metrics, "num_success")8 numErrors := monitoring.NewInt(metrics, "num_errors")9 numSuccess := monitoring.NewInt(metrics, "num_success")10 numErrors := monitoring.NewInt(metrics, "num_errors")11 numSuccess := monitoring.NewInt(metrics, "num_success")12 numErrors := monitoring.NewInt(metrics, "num_errors")13 numSuccess := monitoring.NewInt(metrics, "num_success")

Full Screen

Full Screen

GetBufferedSamples

Using AI Code Generation

copy

Full Screen

1import (2func main() {3 metrics := tally.NewTestScope("test", make(map[string]string))4 timer := metrics.Timer("timer")5 timer.Record(time.Second)6 samples := metrics.Snapshot().GetBufferedSamples()7 for _, sample := range samples {8 fmt.Println(sample.Value)9 }10}11import (12func main() {13 metrics := tally.NewTestScope("test", make(map[string]string))14 counter := metrics.Counter("counter")15 counter.Inc(1)16 samples := metrics.Snapshot().GetBufferedSamples()17 for _, sample := range samples {18 fmt.Println(sample.Value)19 }20}21import (22func main() {23 metrics := tally.NewTestScope("test", make(map[string]string))24 gauge := metrics.Gauge("gauge")25 gauge.Update(1)26 samples := metrics.Snapshot().GetBufferedSamples()27 for _, sample := range samples {28 fmt.Println(sample.Value)29 }30}31import (32func main() {33 metrics := tally.NewTestScope("test", make(map[string]string))34 histogram := metrics.Histogram("histogram", tally.DefaultBuckets)35 histogram.RecordValue(1)36 samples := metrics.Snapshot().GetBufferedSamples()37 for _, sample := range samples {38 fmt.Println(sample.Value)39 }40}

Full Screen

Full Screen

GetBufferedSamples

Using AI Code Generation

copy

Full Screen

1func (m *Metrics) GetBufferedSamples(metricName string) []Sample {2 m.mu.Lock()3 defer m.mu.Unlock()4}5import (6func main() {7 metrics := metric.NewSystem(system.MetricsSystemConfig{})8 s := metrics.NewScope("myscope", nil)9 counter := s.NewCounter("mycounter")10 counter.Inc(1)11 samples := metrics.GetBufferedSamples("myscope.mycounter")12 fmt.Println(samples[0].Value)13}14func (s *Scope) GetBufferedSamples(metricName string) []metric.Sample {15 return s.metrics.GetBufferedSamples(s.Name + "." + metricName)16}17import (18func main() {19 metrics := metric.NewSystem(system.MetricsSystemConfig{})20 s := metrics.NewScope("myscope", nil)21 counter := s.NewCounter("mycounter")22 counter.Inc(1)23 samples := s.GetBufferedSamples("mycounter")24 fmt.Println(samples[0].Value)25}26func (c *counter) GetBufferedSamples(metricName string) []metric.Sample {

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