Running k6 script for load tests returns an error - redirect

I'm first time user of k6 and I've already manage to get an error when running the script:
"Request Failed [33merror[0m="Get https:///: stopped
after 0 redirects"
Script k6.js:
import http from "k6/http";
import { sleep } from "k6";
export let options = {
stages: [
{ duration: "30s", target: 20 },
{ duration: "1m30s", target: 10 },
{ duration: "20s", target: 0 },
]
};
export default function() {
let res = http.get("https://<our_page_URL>/");
check(res, {
"status code MUST be 200": (res) => res.status == 200,
}) || fail("status code was *not* 200");
sleep(1);
}
Why do I get this error and what is the solution?

You have to set up the maxRedirects option; maxRedirects is the maximum number of HTTP redirects that k6 will follow before giving up on a request and erroring out with ("Get $PATH stopped after $MAX_REDIRECT_VALUE redirects")
You can pass the option as CLI argument or script options. More about this option at https://docs.k6.io/docs/options
export let options = {
// Max redirects to follow (default is 10)
maxRedirects: 10
};
The default is 10, so there is likely a bug skipping the default value being assigned.
This is a redirect example to test how it works.
import http from "k6/http";
import {check} from "k6";
export let options = {
// Max redirects to follow (default is 10)
maxRedirects: 5
};
export default function() {
// If redirecting more than options.maxRedirects times, the last response will be returned
let res = http.get("https://httpbin.org/redirect/6");
check(res, {
"is status 302": (r) => r.status === 302
});
// The number of redirects to follow can be controlled on a per-request level as well
res = http.get("https://httpbin.org/redirect/1", {redirects: 1});
console.log(res.status);
check(res, {
"is status 200": (r) => r.status === 200,
"url is correct": (r) => r.url === "https://httpbin.org/get"
});
}

Related

How to solve Vercel 500 Internal Server Error?

I have created a project that uses MongoDB to store user info and Next-Auth to authenticate users. On local host this is all working seamlessly. Previously I had a couple errors with my next-auth config, but that seems to be working fine now on Vercel live site. Once the user logs in they are redirected to "my-project/suggestions". On this page I am using getServerSideProps to identify if there is a valid session token. If so, data is pulled from a local json file.
On the live site, when the user logs in, the page is redirected to "/suggestions", yet I am receiving an 500 Internal Server Error page. On the function logs I am getting this error message:
[GET] /_next/data/KpsnuV9k44lUAhQ-0rK-B/suggestions.json
10:10:57:12
2022-05-05T14:10:59.270Z 5b7a7375-045f-4518-864b-7968c3c9385f ERROR [Error: ENOENT: no such file or directory, open '/var/task/public/data/data.json'] {
errno: -2,
syscall: 'open',
path: '/var/task/public/data/data.json',
page: '/suggestions'
}
RequestId: 5b7a7375-045f-4518-864b-7968c3c9385f Error: Runtime exited with error: exit status 1
Runtime.ExitError
This is my first project using MongoDB and Next-Auth.. not so sure what the issue is in this case. In my .env.local file I only have these two variables:
NEXTAUTH_SECRET="MUNKNATION"
NEXTAUTH_URL=http://localhost:3000
How I am pulling the data on local host:
export const getServerSideProps = async (context) => {
const session = await getSession({ req: context.req });
if (!session) {
return {
redirect: {
destination: "/",
permanent: false,
},
};
} else {
let filePath = path.join(process.cwd(), "public", "data", "data.json");
let jsonData = await fs.readFile(filePath);
const data = JSON.parse(jsonData);
const inProgressStatusData = data.productRequests.filter(
(item) => item.status == "in-progress"
);
const liveStatusData = data.productRequests.filter(
(item) => item.status == "live"
);
const plannedStatusData = data.productRequests.filter(
(item) => item.status == "planned"
);
let filterData = filteredData(data, "suggestion");
let feedbackData = {
suggestions: filterData,
progress: inProgressStatusData,
planned: plannedStatusData,
live: liveStatusData,
};
return {
props: { session, feedbackData },
};
}
};
Folder structure:
A simple solution to this problem would be to, inside of your getServerSideProps, instead of calling readFile use readFileSync as follows:
export const getServerSideProps = async (context) => {
...
const file = readFileSync(
join(process.cwd(), "public", "data", "data.json"),
"utf8"
);
const data = JSON.parse(fileData);
...
I have tested this solution with Vercel and it works correctly, in development and production mode.

How to run post request for multiple user in k6 performance test?

We run Get http request with multiple user(vus) and multiple iteration(iterations) for particular duration.
It is straightforward like below.
import http from 'k6/http';
import { sleep } from 'k6';
export let options ={
vus:'10',
duration: '20s',
iterations: '10'
}
export default function (){
const baseUri = 'http://Myhost:3200'
let response = http.get(`${baseUri}/api/v1/vm-inventory`)
let body = JSON.parse(response.body)
body.items.forEach(element => {
if (element.datastoreIds.length != 0 ){
console.log(JSON.stringify(element))
console.log(`Name of the vm is ${element.name}`)
}
});
sleep(1);
}
I also need to run post request by multiple user and multiple iterations. But all the example I am seeing are related to single post request. When we run multiple post request ,our data need to be changed for every iteration. How it is possible with k6? Below is my post request.
import http from 'k6/http';
import { sleep } from 'k6';
export let options ={
vus:'5',
duration: '120s',
iterations: '5'
}
let payload = `{
"VMId": "70c8b578-32ef-40d2-bcc5-81267423d2c4",
"name": "test_vm_1",
"mem": "4,
"cpu": "2",
"disk": "50gb"
}`
export default function () {
const url = 'http://myhost:3200/api/v1/vm-inventory'
var header = {
headers: {
'Content-Type': 'application/json',
},
};
let res = http.post(url, JSON.stringify(payload),header);
console.log(res.json().json.name);
sleep(5);
}
I need to change the Vm name in payload for every iteration in order the request to be unique.
How to achieve this in k6? In Jmeter , they are reading it from csv with different data for each iteration and achieving it. But I could not find any sample for K6.
we need to create the payload inside the export default function so that we can modify it there before sending it. If the VMId just needs to be a unique UUID, have a look at jslib utils library, which contains a function for generating a uuidv4:
export function uuidv4() {
return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) {
let r = Math.random() * 16 | 0, v = c === 'x' ? r : (r & 0x3 | 0x8);
return v.toString(16);
});
}
Putting it together:
import http from 'k6/http';
import { sleep } from 'k6';
export let options = {
vus: '5',
duration: '120s',
iterations: '5'
}
export default function () {
let payload = {
VMId: uuidv4(),
name: `test_vm_${Date.now()}`,
mem: 4,
cpu: 2,
disk: "50gb"
};
const url = 'http://myhost:3200/api/v1/vm-inventory'
var header = {
headers: {
'Content-Type': 'application/json',
},
};
let res = http.post(url, JSON.stringify(payload), header);
console.log(res.json().json.name);
sleep(5);
}
export function uuidv4() {
return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) {
let r = Math.random() * 16 | 0, v = c === 'x' ? r : (r & 0x3 | 0x8);
return v.toString(16);
});
}
(note that I've changed the payload to a JS object so that it doesn't get stringified twice).
Also we can use the payload like below.
let payload = {
VMId: uuidv4(),
name: `test_vm_vu_${__VU}`,
mem: 4,
cpu: 2,
disk: "50gb"
};
__VU will be giving virtual user number so that we can create test_vm_vu_1,test_vm_vu_3, test_vm_vu_2 . (It will be run in parallel, so the number will not come in sequential manner)
I got this answer from K6 slack community group. I post it here for anybody facing the same situation.

How to find total passed, failed test cases in Protractor?

How to find total passed, failed test cases in Protractor?
Please recommend npm package which serves the problem statement
what's wrong with native Jasmine framework?
okay, if you want the number of describes failed you can add this code in your onPrepare in the config
onPrepare() {
jasmine.getEnv().addReporter({
suites: [],
jasmineStarted: function(suiteInfo) {
let jasmineSuites = jasmine.getEnv().topSuite();
for (let suite of jasmineSuites.children) {
this.suites.push({
suite: suite.description,
status: 'pass',
});
}
},
specDone: function(spec) {
if (spec.status === 'failed') {
let suiteName = spec.fullName.replace(' ' + spec.description, '');
this.suites.find(item => item.suite === suiteName).status = 'failed'
}
},
jasmineDone: function(result) {
let failed = this.suites.filter(item => item.status === 'failed')
console.log('**************************************************')
console.log(`${failed.length} of ${this.suites.length} describe(s) failed`)
console.log('**************************************************')
},
})
}
And it will result this output in your console

401 when calling WLAuthorizationManager.login("scope")

I have implemented the new MFP 8 Beta security concept. The positive case, with valid credentials is working fine and the processSuccess method that I have defined is executed.
Unfortunately, the negative case doesn’t work.
After calling the WLAuthorizationManager.login("scope"), I am getting a 401 in the console:
2016-05-20 13:48:41.965 Inspector[98311:1660747] [DEBUG] [WL_AFHTTPSessionManagerWrapper_PACKAGE] -[WLAFHTTPSessionManagerWrapper start] in WLAFHTTPSessionManagerWrapper.m:376 :: Starting the request with URL http://172.20.10.4:9080/mfp/api/preauth/v1/preauthorize
2016-05-20 13:48:41.983 Inspector[98311:1655477] [DEBUG] [WL_AFHTTPSessionManagerWrapper_PACKAGE] -[WLAFHTTPSessionManagerWrapper requestFailed:responseObject:error:] in WLAFHTTPSessionManagerWrapper.m:419 :: Request Failed
2016-05-20 13:48:41.984 Inspector[98311:1655477] [DEBUG] [WL_AFHTTPSessionManagerWrapper_PACKAGE] -[WLAFHTTPSessionManagerWrapper requestFailed:responseObject:error:] in WLAFHTTPSessionManagerWrapper.m:422 :: Response Status Code : 401
2016-05-20 13:48:41.984 Inspector[98311:1655477] [DEBUG] [WL_AFHTTPSessionManagerWrapper_PACKAGE] -[WLAFHTTPSessionManagerWrapper requestFailed:responseObject:error:] in WLAFHTTPSessionManagerWrapper.m:424 :: Response Error : Request failed: unauthorized (401)
Here is my implementation:
WLAuthorizationManager.login("UserLogin",{
'username':$scope.username,
'password':$scope.password
}).then( function () {
console.log(">> WLAuthorizationManager.login - onSuccess");
$scope.getInspectorDetails().then(
function(){
$scope.loginInProgress = false;
$state.go("inspectionList");
}
);
},
function (response) {
console.log(">> WLAuthorizationManager.login - onFailure: " + JSON.stringify(response));
$scope.loginInProgress = false;
if (!$scope.loginError){
$scope.loginError = "Could not connect to server. Please try again later.";
}
$scope.$apply();
});
}
And the Challenge handler:
$scope.registerChallengeHandler = function(){
console.log(">> in $scope.registerChllangeHandler ... ");
$scope.userLoginChallengeHandler = WL.Client.createWLChallengeHandler($scope.securityCheckName);
$scope.userLoginChallengeHandler.securityCheckName = $scope.securityCheckName;
$scope.userLoginChallengeHandler.handleChallenge = function(challenge) {
console.log(">> in UserLoginChallengeHandler - userLoginChallengeHandler.handleChallenge ...");
// When a session has expired, this will be our entry point into automatically logging back in
// (since the next server call the user tries to make will end up being flagged as a 'custom response'
// which will trigger the challenge hander. Thus, we need to turn on the progress spinner...
$scope.$apply(function(){
$scope.loginInProgress = true;
});
//show the login ...
$scope.user = { username: "", password: ""};
$scope.currentPath = $location.path();
console.log(">> $location.path(): " + $location.path());
if (!$state.is("login")){
$state.go("login");
}
$scope.isChallenged = true;
var statusMsg = "Remaining Attempts: " + challenge.remainingAttempts;
if (challenge.errorMsg !== null){
statusMsg = statusMsg + "<br/>" + challenge.errorMsg;
$timeout(function(){
//want to show only when submit user/pass not when token expired ...
if($scope.currentPath == "/"){
$scope.loginError = statusMsg;
}
}, 300);
}
console.log(">>> statusMsg : " + statusMsg);
};
$scope.userLoginChallengeHandler.processSuccess = function(data) {
console.log(">> in UserLoginChallengeHandler - userLoginChallengeHandler.processSuccess ...");
$scope.isChallenged = false;
$timeout(function(){
$scope.user = { username: "", password: ""};
}, 200);
$state.transitionTo("inspectionList");
};
$scope.userLoginChallengeHandler.handleFailure = function(error) {
console.log(">> in UserLoginChallengeHandler - userLoginChallengeHandler.handleFailure ...");
console.log(">> handleFailure: " + error.failure);
$scope.isChallenged = false;
if (error.failure !== null){
alert(error.failure);
} else {
alert("Failed to login.");
}
};
}
I would have expected that the handleFailure Method is called, but in the debugger I saw that it is not being executed. After the call of WLAuthorizationManager it just stops, so even the WLAuthorizationManager.login – onFailure is not called.
Edit:
Captured the traffic with Wireshark: https://ibm.box.com/s/7mtwsgea06i4bpdbdz0wvyhy3wpma58r
When using WLAuthorizationManager.login() with wrong credentials, the normal flow is that the challenge handler's handleChallenge will be called, to allow the user to try again.
In some cases, the security check might send a failure, such as "maximum attempt reached". In this case, the challenge handler's handleFailure is called.
WLAuthorizationManager.login() has its own failure scenarios. For example, let's say your server is down, there is no network, the security check does not exist, etc. In those cases, since there is no challenge involved, the login's failure will be called. That's when your then promise will come in handy.

Log in to Facebook with phantomjs - 302 issues?

I'm trying to write a phantomjs script to log in to my facebook account and take a screenshot.
Here's my code:
var page = require('webpage').create();
var system = require('system');
var stepIndex = 0;
var loadInProgress = false;
email = system.args[1];
password = system.args[2];
page.onLoadStarted = function() {
loadInProgress = true;
console.log("load started");
};
page.onLoadFinished = function() {
loadInProgress = false;
console.log("load finished");
};
var steps = [
function() {
page.open("http://www.facebook.com/login.php", function(status) {
page.evaluate(function(email, password) {
document.querySelector("input[name='email']").value = email;
document.querySelector("input[name='pass']").value = password;
document.querySelector("#login_form").submit();
console.log("Login submitted!");
}, email, password);
page.render('output.png');
});
},
function() {
console.log(document.documentElement.innerHTML);
},
function() {
phantom.exit();
}
]
setInterval(function() {
if (!loadInProgress && typeof steps[stepIndex] == "function") {
console.log("step " + (stepIndex + 1));
steps[stepIndex]();
stepIndex++;
}
if (typeof steps[stepIndex] != "function") {
console.log("test complete!");
phantom.exit();
}
}, 10000);
(Inspired by this answer, but note that I've upped the interval to 10s)
Called like so:
./phantomjs test.js <email> <password>
With output (filtering out the selfxss warnings from Facebook):
step 1
load started
load finished
Login submitted!
load started
load finished
step 2
<head></head><body></body>
step 3
test
complete!
(Note that the html output in step two is empty)
This answer suggests that there are problems with phantomjs' SSL options, but running with --ssl-protocol=any has no effect.
This appears to be a similar problem, but for caspar, not phantomjs (and on Windows, not Mac) - I've tried using --ignore-ssl-errors=yes, but that also had no effect.
I guessed that this might be a redirection problem (and, indeed, when I replicate this on Chrome, the response from clicking "Submit" was a 302 Found with location https://www.facebook.com/checkpoint/?next), but according to this documentation I can set a page.onNavigationRequested handler - when I do so in my script, it doesn't get called.
I think this issue is related, but it looks as if there's no fix there.