Best JavaScript code snippet using redwood
executionengine work in progress.js
Source:executionengine work in progress.js
...369 }370 newMachine.threadID = i+startThread-1;371 common.logger.info(newMachine);372 executions[executionID].machines.push(newMachine);373 sendAgentCommand(newMachine.host,newMachine.port,{command:"start launcher",executionID:executionID,threadID:newMachine.threadID},3,function(err){374 newMachineCount++;375 if (newMachineCount == machine.threads){376 count++;377 if(count == mainMachinesCount){378 callback();379 }380 }381 });382 }383 });384 }385 else{386 count++;387 if(count == mainMachinesCount){388 callback();389 }390 }391 });392 });393 });394}395function suiteBaseState(executionID,machines,callback){396 var count = 0;397 var foundSuiteState = false;398 var suiteBaseTCs = [];399 var lastMachine = function(){400 if (count === machines.length){401 if (suiteBaseTCs.length > 0){402 executions[executionID].cachedTCs = executions[executionID].testcases;403 executions[executionID].testcases = {};404 suiteBaseTCs.forEach(function(tc){405 executions[executionID].testcases[tc.testcaseID] = tc;406 });407 executions[executionID].baseStateFailed = false;408 }409 callback()410 }411 };412 machines.forEach(function(machine){413 if(machine.baseState){414 foundSuiteState = true;415 machine.roles.push(machine.host);416 db.collection('testcases', function(err, collection) {417 collection.insert({baseState:true,name:machine.host+"_state",status:"Automated",type:"collection",collection:[{order:"1",actionid:machine.baseState,host:machine.host,executionflow:"Record Error Stop Test Case",parameters:[]}]}, {safe:true},function(err,testcaseData){418 db.collection('executiontestcases', function(err, collection) {419 //collection.save({_id:machine.resultID},{},{$set:{executionID:executionID,name:machine.host+"_state",status:"Not Run",testcaseID:testcaseData[0]._id.__id,_id: machine.resultID}}, {safe:true,new:true},function(err,returnData){420 collection.save({baseState:true,executionID:executionID,name:machine.host+"_state",status:"Not Run",testcaseID:testcaseData[0]._id.__id,_id: machine.baseStateTCID},function(err,returnData){421 suiteBaseTCs.push({testcaseID:testcaseData[0]._id.__id,retryCount:0,_id:machine.baseStateTCID,status:"Not Run",name:machine.host+"_state",type:"collection"});422 count++;423 lastMachine();424 });425 });426 });427 });428 }429 else{430 count++;431 }432 lastMachine();433 });434}435exports.cacheSourceCode = function(rootPath,callback){cacheSourceCode(rootPath,callback)};436function cacheSourceCode(rootPath,callback){437 git.lsFiles(rootPath,["*.groovy","*.java"],function(data){438 var files = [];439 if ((data != "")&&(data.indexOf("\n") != -1)){440 files = data.split("\n",data.match(/\n/g).length);441 }442 callback(files);443 })444}445function getGlobalVars(executionID,callback){446 db.collection('variables', function(err, collection) {447 collection.find({taskVar:false}, {}, function(err, cursor) {448 cursor.each(function(err, variable) {449 if(variable == null) {450 callback();451 }452 else{453 executions[executionID].variables[variable.name] = variable.value;454 }455 });456 })457 });458}459function cleanUpMachines(machines,executionID,callback){460 var count = 0;461 machines.forEach(function(machine){462 sendAgentCommand(machine.host,machine.port,{command:"cleanup",executionID:executionID},3,function(err){463 count++;464 if(count == machines.length){465 if(callback) callback();466 }467 });468 })469}470function executeTestCases(testcases,executionID){471 if (!executions[executionID]) return;472 executions[executionID].executingTCs = true;473 var variables = executions[executionID].variables;474 var machines = executions[executionID].machines;475 var tcArray = [];476 for(var key in testcases){477 tcArray.push(key);478 }479 //execution all done480 //if (tcArray.length == 0){481 var finishExecution = function(callback){482 if (executions[executionID].cachedTCs){483 if(executions[executionID].baseStateFailed === true){484 unlockCloudMachines(executions[executionID].machines);485 unlockMachines(machines,function(){486 cleanUpMachines(executions[executionID].machines,executionID,function(){487 });488 updateExecution({_id:executionID},{$set:{status:"Ready To Run"}},true,function(){489 executionsRoute.updateExecutionTotals(executionID,function(){490 if(executions[executionID].sendEmail == true) sendNotification(executionID);491 //git.deleteFiles(path.join(__dirname, '../public/automationscripts/'+executions[executionID].project+"/"+executions[executionID].username+"/build"),os.tmpDir()+"/jar_"+executionID);492 deleteDir(os.tmpDir()+"/jar_"+executionID);493 delete executions[executionID];494 });495 });496 callback(true)497 });498 return;499 }500 executions[executionID].machines.forEach(function(machine){501 machine.baseState = null;502 });503 executions[executionID].testcases = executions[executionID].cachedTCs;504 delete executions[executionID].cachedTCs;505 tcArray = [];506 for(key in executions[executionID].testcases){507 tcArray.push(key);508 }509 testcases = executions[executionID].testcases;510 callback(false)511 }512 else{513 if(executions[executionID]){514 unlockCloudMachines(executions[executionID].machines);515 unlockMachines(executions[executionID].machines,function(){516 cleanUpMachines(executions[executionID].machines,executionID,function(){517 });518 updateExecution({_id:executionID},{$set:{status:"Ready To Run"}},true,function(){519 executionsRoute.updateExecutionTotals(executionID,function(){520 if(executions[executionID].sendEmail == true) sendNotification(executionID);521 //git.deleteFiles(path.join(__dirname, '../public/automationscripts/'+executions[executionID].project+"/"+executions[executionID].username+"/build"),os.tmpDir()+"/jar_"+executionID);522 deleteDir(os.tmpDir()+"/jar_"+executionID);523 delete executions[executionID];524 });525 });526 callback(true)527 });528 }529 //return;530 }531 };532 var count = 0;533 var doneCount = 0;534 var nextTC = function(){535 if (!testcases[tcArray[count]]){536 executions[executionID].executingTCs = false;537 return;538 }539 if (testcases[tcArray[count]].executing == true){540 count++;541 nextTC();542 return;543 }544 else if(testcases[tcArray[count]].finished == true){545 count++;546 doneCount++;547 if (doneCount == tcArray.length){548 finishExecution(function(finishIt){549 if(finishIt == false){550 count = 0;551 nextTC();552 }553 else{554 if(executions[executionID]) executions[executionID].executingTCs = false;555 }556 });557 return;558 }559 nextTC();560 return;561 }562 testcases[tcArray[count]].executing = true;563 startTCExecution(testcases[tcArray[count]].testcaseID,variables,executionID,function(){564 if (!executions[executionID]) return;565 count++;566 var machineAvailable = false;567 machines.forEach(function(machine){568 if(machine.runningTC == undefined){569 machineAvailable = true;570 }571 });572 if((count < tcArray.length)&&(machineAvailable == true)){573 nextTC();574 }575 else{576 executions[executionID].executingTCs = false;577 //remove any useless machines578 var toRemove = [];579 machines.forEach(function(machine){580 if(machine.runningTC == undefined){581 //don't remove any machines if this is just a suite base state that is running582 if(!executions[executionID].cachedTCs){583 toRemove.push(machine)584 }585 }586 });587 unlockMachines(toRemove,function(){588 toRemove.forEach(function(machine){589 machines.splice(machines.indexOf(machine),1);590 });591 });592 //if nothing else to execute finish it.593 var somethingToRun = false;594 tcArray.forEach(function(testcaseCount){595 if(testcases[testcaseCount].finished != true){596 somethingToRun = true;597 }598 });599 if(somethingToRun == false){600 finishExecution(function(finishIt){601 if(finishIt == false){602 count = 0;603 nextTC();604 }605 else{606 if(executions[executionID]) executions[executionID].executingTCs = false;607 }608 });609 }610 }611 });612 };613 if (count == 0) nextTC();614}615function startTCExecution(id,variables,executionID,callback){616 GetTestCaseDetails(id,executionID,function(testcase,result,hosts){617 if(testcase == null){618 callback();619 return;620 }621 testcase.machines = [];622 testcase.machineVars = [];623 var reservedHosts = [];624 var busyMachines = false;625 executions[executionID].machines.forEach(function(machine,index){626 if(machine.runningTC != undefined){627 busyMachines = true;628 }629 hosts.forEach(function(host){630 if((machine.roles.indexOf(host) != -1)&& (reservedHosts.indexOf(host) == -1) &&((machine.runningTC == undefined)||(machine.runningTC == testcase))){631 machine.runningTC = testcase;632 reservedHosts.push(host);633 testcase.machines.push(machine);634 machine.roles.forEach(function(role){635 if (machine.machineVars){636 machine.machineVars.forEach(function(variable){637 testcase.machineVars["Machine."+role+"."+variable.name] = variable.value638 });639 }640 testcase.machineVars["Machine."+role+".Host"] = machine.host;641 testcase.machineVars["Machine."+role+".Port"] = machine.port;642 })643 }644 });645 });646 if ((testcase.machines.length == 0) || (reservedHosts.length != hosts.length)){647 if(busyMachines == true){648 executions[executionID].testcases[id].executing = false;649 callback();650 return;651 }652 }653 result.status = "Running";654 createResult(result,function(writtenResult){655 result._id = writtenResult[0]._id;656 result.executionID = executionID;657 executions[executionID].currentTestCases[testcase.dbTestCase._id] = {testcase:testcase,result:result,executionTestCaseID:id};658 //testcase.machines = [];659 testcase.startDate = new Date();660 if (((testcase.dbTestCase.status != "Automated")||(testcase.statusError)) && (executions[executionID].ignoreStatus == false)){661 var error = "";662 if (testcase.statusError){663 error = testcase.statusError664 }else if(testcase.dbTestCase.status == "To be Automated"){665 error = "Test Case is not Automated"666 }else if(testcase.dbTestCase.status == "Needs Maintenance"){667 error = "Test Case Needs Maintenance"668 }669 //if (callback){670 // callback({error:error});671 //}672 result.error = testcase.dbTestCase.status;673 result.status = "Not Run";674 //result.result = testcase.dbTestCase.status;675 result.result = error;676 updateResult(result);677 //executions[executionID].testcases[id].result = result;678 finishTestCaseExecution(executions[executionID],executionID,executions[executionID].testcases[id]._id,executions[executionID].currentTestCases[testcase.dbTestCase._id]);679 callback();680 return;681 }682 //if there is nothing to execute just finish the TC683 if (((testcase.dbTestCase.type === "collection")&&(testcase.actions.length == 0)) || ((testcase.dbTestCase.type === "script")&&(testcase.dbTestCase.script == ""))){684 //if (callback){685 // callback();686 //}687 result.status = "Finished";688 result.result = "Passed";689 updateResult(result);690 finishTestCaseExecution(executions[executionID],executionID,executions[executionID].testcases[id]._id,executions[executionID].currentTestCases[testcase.dbTestCase._id]);691 callback();692 return;693 }694 //updateExecutionTestCase({_id:testcases[0]._id.executionTestCaseID},{$set:{"status":"Running"}});695 var machines = executions[executionID].machines;696 machines.sort(function(a,b){697 return a.roles.length - b.roles.length;698 });699 /*700 var reservedHosts = [];701 testcase.machines = [];702 testcase.machineVars = [];703 machines.forEach(function(machine,index){704 hosts.forEach(function(host){705 if((machine.roles.indexOf(host) != -1)&& (reservedHosts.indexOf(host) == -1) &&((machine.runningTC == undefined)||(machine.runningTC == testcase))){706 machine.runningTC = testcase;707 reservedHosts.push(host);708 testcase.machines.push(machine);709 machine.roles.forEach(function(role){710 if (machine.machineVars){711 machine.machineVars.forEach(function(variable){712 testcase.machineVars["Machine."+role+"."+variable.name] = variable.value713 });714 }715 testcase.machineVars["Machine."+role+".Host"] = machine.host;716 testcase.machineVars["Machine."+role+".Port"] = machine.port;717 })718 }719 });720 });721 */722 if ((testcase.machines.length == 0) || (reservedHosts.length != hosts.length)){723 //if (callback){724 // callback({error:"Unable to find matching machine for this test case. Roles required are:"+hosts.join()});725 //}726 //updateExecutionTestCase({_id:executions[executionID].testcases[id]._id},{$set:{"status":"Finished",result:"Failed",resultID:result._id,error:"Unable to find matching machine for this test case. Roles required are:"+hosts.join()}});727 result.error = "Unable to find matching machine for this test case. Roles required are:"+hosts.join();728 result.status = "Finished";729 result.result = "Failed";730 updateResult(result);731 finishTestCaseExecution(executions[executionID],executionID,executions[executionID].testcases[id]._id,executions[executionID].currentTestCases[testcase.dbTestCase._id]);732 callback();733 return;734 }735 var count = 0;736 var errorFound = false;737 //var startTC = function(){738 var agentInstructions = {command:"run action",executionID:executionID,testcaseID:testcase.dbTestCase._id,variables:executions[executionID].variables};739 var foundMachine = null;740 var runBaseState = function(){741 agentBaseState(executions[executionID].project+"/"+executions[executionID].username,executionID,foundMachine.host,foundMachine.port,foundMachine.threadID,function(err){742 if (err){743 result.error = err.error;744 result.status = "Finished";745 result.result = "Failed";746 updateResult(result);747 if (executions[executionID]){748 executions[executionID].currentTestCases[testcase.dbTestCase._id].result = result;749 finishTestCaseExecution(executions[executionID],executionID,executions[executionID].testcases[id]._id,executions[executionID].currentTestCases[testcase.dbTestCase._id]);750 }751 }752 else{753 foundMachine.runBaseState = true;754 sendAgentCommand(foundMachine.host,foundMachine.port,agentInstructions,3);755 }756 });757 };758 //if test case is a script and NOT an action collection759 if (testcase.dbTestCase.type !== "collection"){760 if ((testcase.script == "") || (!testcase.script)){761 result.error = "Test Case does not have a script assigned";762 result.status = "Finished";763 result.result = "Failed";764 updateResult(result);765 //executions[executionID].testcases[id].result = result;766 finishTestCaseExecution(executions[executionID],executionID,executions[executionID].testcases[id]._id,executions[executionID].currentTestCases[testcase.dbTestCase._id]);767 return;768 }769 agentInstructions.name = testcase.name;770 agentInstructions.ignoreScreenshots = executions[executionID].ignoreScreenshots;771 agentInstructions.allScreenshots = executions[executionID].allScreenshots;772 agentInstructions.executionID = executionID;773 agentInstructions.testcaseName = testcase.name;774 agentInstructions.script = testcase.script;775 agentInstructions.scriptLang = testcase.scriptLang;776 agentInstructions.resultID = result._id.__id;777 agentInstructions.parameters = [];778 agentInstructions.type = testcase.dbTestCase.type;779 var actionHost = "Default";780 //if(action.dbAction.host != "") actionHost = action.dbAction.host;781 testcase.machines.forEach(function(machine){782 if ((machine.roles.indexOf(actionHost) != -1)&&(foundMachine == null)){783 foundMachine = machine;784 }785 });786 agentInstructions.threadID = foundMachine.threadID;787 updateExecutionTestCase({_id:executions[executionID].testcases[id]._id},{$set:{"status":"Running","result":"",error:"",trace:"",resultID:result._id,startdate:testcase.startDate,enddate:"",runtime:"",host:foundMachine.host,vncport:foundMachine.vncport}},foundMachine.host,foundMachine.vncport);788 executionsRoute.updateExecutionTotals(executionID);789 if (foundMachine.runBaseState === true){790 if (foundMachine.multiThreaded == true){791 sendAgentCommand(foundMachine.host,foundMachine.port,agentInstructions,3);792 }793 else{794 //make sure the files are actually there, in case of revert to snapshot or not persistent VMs files795 //could have changed while test case was running796 sendAgentCommand(foundMachine.host,foundMachine.port,{command:"files loaded",executionID:executionID},3,function(message){797 if (message.loaded == true){798 sendAgentCommand(foundMachine.host,foundMachine.port,agentInstructions,3);799 }800 else{801 runBaseState();802 }803 });804 }805 }806 else{807 runBaseState();808 }809 callback();810 return;811 }812 callback();813 for (var attrname in testcase.machineVars) { variables[attrname] = testcase.machineVars[attrname]; }814 variables["Framework.TestCaseName"] = testcase.dbTestCase.name;815 findNextAction(testcase.actions,variables,function(action){816 if (!executions[executionID]) return;817 if(!executions[executionID].currentTestCases[testcase.dbTestCase._id]) return;818 if(action == null){819 finishTestCaseExecution(executions[executionID],executionID,executions[executionID].testcases[id]._id,executions[executionID].currentTestCases[testcase.dbTestCase._id]);820 return;821 }822 executions[executionID].currentTestCases[testcase.dbTestCase._id].currentAction = action;823 agentInstructions.name = action.name;824 agentInstructions.executionflow = action.dbAction.executionflow;825 agentInstructions.executionID = executionID;826 agentInstructions.ignoreScreenshots = executions[executionID].ignoreScreenshots;827 agentInstructions.allScreenshots = executions[executionID].allScreenshots;828 agentInstructions.returnValueName = action.dbAction.returnvalue;829 agentInstructions.testcaseName = testcase.dbTestCase.name;830 agentInstructions.script = action.script;831 agentInstructions.scriptLang = action.scriptLang;832 agentInstructions.resultID = result._id.__id;833 agentInstructions.parameters = [];834 action.dbAction.parameters.forEach(function(parameter){835 agentInstructions.parameters.push({name:parameter.paramname,value:parameter.paramvalue});836 });837 var actionHost = "Default";838 if(action.dbAction.host != "") actionHost = action.dbAction.host;839 testcase.machines.forEach(function(machine){840 if ((machine.roles.indexOf(actionHost) != -1)&&(foundMachine == null)){841 foundMachine = machine;842 }843 });844 agentInstructions.threadID = foundMachine.threadID;845 updateExecutionTestCase({_id:executions[executionID].testcases[id]._id},{$set:{"status":"Running","result":"",error:"",trace:"",resultID:result._id,startdate:testcase.startDate,enddate:"",runtime:"",host:foundMachine.host,vncport:foundMachine.vncport}},foundMachine.host,foundMachine.vncport);846 if ((testcase.machines.length > 0) &&((testcase.machines[0].baseState))){847 updateExecutionMachine(executionID,testcase.machines[0]._id,"",result._id.__id);848 }849 executionsRoute.updateExecutionTotals(executionID);850 if (foundMachine.runBaseState === true){851 if (foundMachine.multiThreaded == true){852 sendAgentCommand(foundMachine.host,foundMachine.port,agentInstructions,3);853 }854 else{855 //make sure the files are actually there, in case of revert to snapshot or not persistent VMs files856 //could have changed while test case was running857 sendAgentCommand(foundMachine.host,foundMachine.port,{command:"files loaded",executionID:executionID},3,function(message){858 if (message.loaded == true){859 sendAgentCommand(foundMachine.host,foundMachine.port,agentInstructions,3);860 }861 else{862 runBaseState();863 }864 });865 }866 }867 else{868 runBaseState();869 }870 });871 })872 });873}874exports.logPost = function(req,res){875 var record = req.body;876 var executionID = record.executionID.replace(/-/g, '');877 delete record.command;878 delete record.executionID;879 db.collection('executionlogs'+executionID, function(err, collection) {880 collection.insert(record, {safe:true},function(err,returnData){881 res.contentType('json');882 res.json({success:true});883 realtime.emitMessage("AddExecutionLog",record);884 });885 });886};887exports.actionresultPost = function(req, res){888 res.contentType('json');889 res.json({success:true});890 var execution = executions[req.body.executionID];891 if (!execution) return;892 var testcase = execution.currentTestCases[req.body.testcaseID];893 if (testcase == undefined) return;894 if (testcase.testcase.script){895 testcase.result.status = "Finished";896 testcase.result.result = req.body.result;897 if (req.body.error){898 testcase.result.error = req.body.error;899 }900 else{901 testcase.result.error = "";902 }903 if (req.body.trace){904 formatTrace(req.body.trace,execution.sourceCache,function(trace){905 testcase.result.trace = trace;906 if(trace == "") testcase.result.trace = req.body.trace;907 updateResult(testcase.result);908 });909 }910 else{911 updateResult(testcase.result);912 }913 finishTestCaseExecution(execution,req.body.executionID,execution.testcases[testcase.executionTestCaseID]._id,testcase);914 return;915 }916 testcase.currentAction.result.status = "Finished";917 testcase.currentAction.result.result = req.body.result;918 if(!testcase.result.error){919 testcase.result.error = "";920 }921 if (req.body.error){922 testcase.result.error = req.body.error;923 testcase.currentAction.result.error = req.body.error;924 }925 if (req.body.trace){926 testcase.result.trace = req.body.trace;927 testcase.currentAction.result.trace = req.body.trace;928 testcase.trace = req.body.trace;929 }930 if (req.body.screenshot){931 testcase.result.screenshot = req.body.screenshot;932 testcase.currentAction.result.screenshot = req.body.screenshot;933 }934 if ((req.body.returnValue)&&(testcase.currentAction.dbAction.returnvalue != "")){935 if(!execution.returnVars[req.body.testcaseID]){936 execution.returnVars[req.body.testcaseID] = {};937 }938 execution.returnVars[req.body.testcaseID][testcase.currentAction.dbAction.returnvalue] = req.body.returnValue;939 //.[testcase.currentAction.dbAction.returnvalue] = req.body.returnValue;940 //execution.variables[testcase.currentAction.dbAction.returnvalue] = req.body.returnValue;941 }942 var actionFlow = testcase.currentAction.dbAction.executionflow;943 if (req.body.result == "Failed"){944 if (actionFlow == "Record Error Stop Test Case"){945 testcase.result.status = "Finished";946 testcase.result.result = "Failed";947 testcase.runAfterState = true;948 testcase.testcase.actions.forEach(function(action){949 if(!action.dbAction.afterState == true){950 action.runAction = false;951 }952 });953 //updateExecutionTestCase({_id:execution.testcases[testcase.executionTestCaseID]._id},{$set:{error:testcase.result.error,trace:testcase.trace}});954 /*955 markFinishedResults(testcase.result.children,execution.sourceCache,function(){956 updateResult(testcase.result);957 });958 finishTestCaseExecution(execution,req.body.executionID,execution.testcases[testcase.executionTestCaseID]._id,testcase);959 return;960 */961 }962 else if (actionFlow == "Record Error Continue Test Case"){963 testcase.result.result = "Failed";964 updateExecutionTestCase({_id:execution.testcases[testcase.executionTestCaseID]._id},{$set:{result:"Failed",trace:testcase.trace}});965 }966 else{967 testcase.currentAction.result.result = "";968 testcase.currentAction.result.trace = "";969 testcase.currentAction.result.error = "";970 testcase.result.result = "";971 testcase.result.error = "";972 }973 }974 markFinishedResults(testcase.result.children,execution.sourceCache,function(){975 updateResult(testcase.result);976 });977 var actionVariables = {};978 for (var attrname in execution.variables) { actionVariables[attrname] = execution.variables[attrname]; }979 for (var attrname in testcase.machineVars) { actionVariables[attrname] = testcase.machineVars[attrname]; }980 if(execution.returnVars[testcase.executionTestCaseID]){981 for (var attrname in execution.returnVars[testcase.executionTestCaseID]) { actionVariables[attrname] = execution.returnVars[testcase.executionTestCaseID][attrname]; }982 }983 findNextAction(testcase.testcase.actions,actionVariables,function(action){984 if(action == null){985 testcase.result.status = "Finished";986 if(testcase.result.result != "Failed") testcase.result.result = "Passed";987 updateResult(testcase.result);988 finishTestCaseExecution(execution,req.body.executionID,execution.testcases[testcase.executionTestCaseID]._id,testcase);989 return;990 }991 var foundMachine = null;992 var actionHost = "Default";993 if(action.dbAction.host != "") actionHost = action.dbAction.host;994 testcase.testcase.machines.forEach(function(machine){995 if ((machine.roles.indexOf(actionHost) != -1)&&(foundMachine == null)){996 foundMachine = machine;997 }998 });999 updateExecutionTestCase({_id:execution.testcases[testcase.executionTestCaseID]._id},{$set:{"status":"Running","result":"",host:foundMachine.host,vncport:foundMachine.vncport}},foundMachine.host,foundMachine.vncport);1000 testcase.result.status = "Running";1001 var agentInstructions = {command:"run action",executionID:req.body.executionID,threadID:foundMachine.threadID,testcaseID:testcase.testcase.dbTestCase._id,variables:execution.variables};1002 execution.currentTestCases[testcase.testcase.dbTestCase._id].currentAction = action;1003 agentInstructions.name = action.name;1004 agentInstructions.executionflow = action.dbAction.executionflow;1005 agentInstructions.executionID = req.body.executionID;1006 agentInstructions.ignoreScreenshots = executions[req.body.executionID].ignoreScreenshots;1007 agentInstructions.allScreenshots = executions[req.body.executionID].allScreenshots;1008 agentInstructions.returnValueName = action.dbAction.returnvalue;1009 agentInstructions.testcaseName = testcase.testcase.dbTestCase.name;1010 agentInstructions.script = action.script;1011 agentInstructions.scriptLang = action.scriptLang;1012 agentInstructions.resultID = testcase.result._id.__id;1013 agentInstructions.parameters = [];1014 action.dbAction.parameters.forEach(function(parameter){1015 agentInstructions.parameters.push({name:parameter.paramname,value:parameter.paramvalue});1016 });1017 var runBaseState = function(){1018 agentBaseState(execution.project+"/"+execution.username,req.body.executionID,foundMachine.host,foundMachine.port,foundMachine.threadID,function(err){1019 if (err){1020 testcase.result.error = err.error;1021 testcase.result.status = "Finished";1022 testcase.result.result = "Failed";1023 updateResult(testcase.result);1024 if (execution){1025 execution.currentTestCases[testcase.dbTestCase._id].result = "Failed";1026 finishTestCaseExecution(execution,req.body.executionID,execution.testcases[id]._id,execution.currentTestCases[testcase.dbTestCase._id]);1027 }1028 }1029 else{1030 foundMachine.runBaseState = true;1031 sendAgentCommand(foundMachine.host,foundMachine.port,agentInstructions,3);1032 }1033 });1034 };1035 if (foundMachine.runBaseState === true){1036 if (foundMachine.multiThreaded == true){1037 sendAgentCommand(foundMachine.host,foundMachine.port,agentInstructions,3);1038 }1039 else{1040 //make sure the files are actually there, in case of revert to snapshot or not persistent VMs files1041 //could have changed while test case was running1042 sendAgentCommand(foundMachine.host,foundMachine.port,{command:"files loaded",executionID:req.body.executionID},3,function(message){1043 if (message.loaded == true){1044 sendAgentCommand(foundMachine.host,foundMachine.port,agentInstructions,3);1045 }1046 else{1047 runBaseState();1048 }1049 });1050 }1051 }1052 else{1053 runBaseState();1054 }1055 });1056};1057//last action or we are done with the TC1058//start next test case if there is one1059function finishTestCaseExecution(execution,executionID,testcaseId,testcase){1060 //updateExecutionTestCase({_id:execution.testcases[testcase.executionTestCaseID]._id},{$set:{"status":"Finished",result:testcase.result.result}});1061 var date = new Date();1062 var status = "Finished";1063 var qcStatus = 'Passed';1064 if((testcase.result.result != "Passed") && (testcase.result.result != "Failed")){1065 status = "Not Run";1066 }1067 1068 switch (testcase.result.result){1069 case "Passed":1070 qcStatus = 'Passed';1071 break;1072 case "Failed":1073 qcStatus = 'Failed';1074 break;1075 default:1076 qcStatus = 'N/A';1077 }1078 1079 var updateTC = function(){1080 updateExecutionTestCase({_id:testcaseId},{$set:{trace:testcase.trace,"status":status,resultID:testcase.result._id.__id,result:testcase.result.result,error:testcase.result.error,enddate:date,runtime:date-testcase.testcase.startDate,host:"",vncport:""}});1081 executionsRoute.updateExecutionTotals(executionID);1082 1083 //set the correct options for the call.1084 var options = {1085 host : "http://alm.cat.com", 1086 path : "/qcbin/authentication-point/authenticate",1087 method: "GET",1088 headers : {'Authorization': 'Basic '+new Buffer("banovm" + ':' + "Boschkins29/").toString('base64')}1089 };1090 //authenticating the user into ALM1091 ALMConnect(options, 'header','', function(status, data){1092 if(status){1093 //get the LWSSO_Cookie from the header. This is the session cookie which will be used in all callouts to ALM.1094 if(data.headers["set-cookie"] != undefined ) {1095 createTest(data.headers["set-cookie"]);1096 }else{1097 console.log('ERROR: Unable to login, check your username/password/serverURL.');1098 }1099 }else{1100 console.log('ERROR: ' + JSON.stringify(data));1101 }1102 });1103 1104 //Function to extract the defects for analysis.1105 function createTest(LWSSO_Cookie){1106 /*var queryParam = "{";1107 //add Release1108 queryParam += "detected-in-rel["+config.release+"];";1109 //add all your request parameters here. Its a little complicated initially, but you will get a hang of it. 1110 // Make sure to use encodeURIComponents() for all the values in the query parameters.1111 queryParam+="}";*/1112 //get all the fields that you want to query. Lesser the fields smaller the XML returned, faster is the call.1113 var fields = config.defectFieldMapping.fieldArray.join(',');1114 var opt = {1115 host: config.host,1116 path: "/qcbin/rest/domains/"+"APD"+"/projects/"+"Minestar_QA_Copy"+"/tests",1117 method:"POST",1118 headers: {"Cookie":LWSSO_Cookie}1119 };1120 1121 var body = '{"Fields":[{"Name":"TS_NAME","values":[{"value":"new test case"}]},{"Name":"TS_TYPE","values":[{"value":"VAPI-XP"}]},]}'1122 1123 ALMConnect(opt, 'data',body,function(status,data){1124 if(status){1125 //write the defects to an XML file in local drive.1126 //fs.writeFileSync('newDefect.xml',data);1127 //once you get the defectXML you can parse it into JSON and push it other databases like SFDC etc.. 1128 }else{1129 console.log('ERROR: ' + JSON.stringify(data));1130 }1131 });1132 }1133 1134 function ALMConnect(opt, responseType,requestBody, callback){1135 1136 var request = https.request(opt, function(res){1137 res.setEncoding('utf8');1138 var XMLoutput='';1139 res.on('data',function(chunk){1140 XMLoutput+=chunk;1141 });1142 res.on('end',function(){1143 if(responseType=='data'){1144 callback(true,XMLoutput);1145 }else {1146 callback(true, res);1147 }1148 });1149 });1150 request.on('error',function(e){1151 callback(false,e);1152 });1153 if(opt.method=='POST' || opt.method == 'PUT'){1154 request.write(requestBody);1155 }1156 request.end();1157 }1158 1159 /*unirest.post('http://localhost:8080/bumblebee/updateqc')1160 .headers({1161 'Accept-Encoding': 'gzip,deflate'1162 })1163 .query({1164 url: 'https://alm.cat.com/qcbin',1165 user: 'banovm',1166 encrypted_password: 'Xn3A404GommvK3pL7GrYoQ==',1167 domain: 'APD',1168 project: 'Minestar_QA_Copy',1169 testplandirectory: 'Subject\\Testing\\Redwood',1170 testname: testcase.testcase.dbTestCase.name,1171 mode: 'FULL',1172 testset: 'Redwood Tests',1173 testlabdirectory: 'Root\\Testing',1174 message: 'Step performed',1175 status: qcStatus,1176 overwrite_runs: 'false'1177 })1178 .end(function (response) {1179 console.log(response.body);1180 });*/1181 1182 };1183 //update machine base state result1184 if(execution.cachedTCs){1185 if (testcase.testcase.machines.length > 0){1186 updateExecutionMachine(executionID,testcase.testcase.machines[0]._id,testcase.result.result,testcase.result._id.__id,function(){1187 updateTC();1188 });1189 }1190 else{1191 updateTC();1192 }1193 //updateExecutionMachine({testcase.testcase.machines[0]._id)},{$set:{result:testcase.result.result,resultID:testcase.result._id.__id}});1194 }1195 else{1196 updateTC();1197 }1198 var count = 0;1199 var retry = false;1200 if(testcase.result.result == "Failed"){1201 if (execution.testcases[testcase.executionTestCaseID].retryCount > 0){1202 retry = true;1203 execution.testcases[testcase.executionTestCaseID].retryCount--;1204 execution.testcases[testcase.executionTestCaseID].executing = false;1205 execution.returnVars[testcase.executionTestCaseID] = {};1206 }1207 if (execution.cachedTCs){1208 execution.baseStateFailed = true;1209 }1210 }1211 if(testcase.testcase.machines.length === 0){1212 if (retry == false){1213 //delete execution.testcases[testcase.executionTestCaseID];1214 execution.testcases[testcase.executionTestCaseID].finished = true;1215 execution.testcases[testcase.executionTestCaseID].executing = false;1216 }1217 delete execution.currentTestCases[testcase.executionTestCaseID];1218 executeTestCases(execution.testcases,executionID);1219 return;1220 }1221 testcase.testcase.machines.forEach(function(machine){1222 delete machine.runningTC;1223 count++;1224 if (count == testcase.testcase.machines.length){1225 if (retry == false){1226 //delete execution.testcases[testcase.executionTestCaseID];1227 execution.testcases[testcase.executionTestCaseID].finished = true;1228 execution.testcases[testcase.executionTestCaseID].executing = false;1229 }1230 delete execution.currentTestCases[testcase.executionTestCaseID];1231 if(execution.executingTCs != true){1232 executeTestCases(execution.testcases,executionID);1233 }1234 }1235 });1236}1237exports.formatTrace = function(trace,sourceCache,callback){formatTrace(trace,sourceCache,callback)};1238function formatTrace(trace,sourceCache,callback){1239 var newTrace = "";1240 var traceCount = 0;1241 var traces = trace.split(",");1242 traces.forEach(function(line){1243 traceCount++;1244 var fileName = line.substring(line.indexOf("(")+1,line.indexOf(":"));1245 var lineNumber = line.substring(line.indexOf(":")+1,line.indexOf(")"));1246 var location = line.substring(0,line.indexOf("("));1247 location = location.trim();1248 location = location.replace("[","");1249 var count = 0;1250 var found = false;1251 if((location.indexOf("org.codehaus.") != -1) || (location.indexOf("java.lang.") != -1) || (location.indexOf("groovy.lang.") != -1) || (location.indexOf("redwood.launcher.") != -1)|| (location.indexOf("sun.reflect.") != -1)){1252 if (line.indexOf("[") == 0){1253 newTrace += line;1254 }1255 else{1256 newTrace += ",\r\n"+line;1257 }1258 if (traceCount == traces.length){1259 callback(newTrace);1260 }1261 return;1262 }1263 if ((fileName.indexOf(".groovy") != -1) ||(fileName.indexOf(".java") != -1)){1264 sourceCache.forEach(function(file){1265 if (found == true) return;1266 if (file.indexOf("/"+fileName) != -1){1267 if(location.replace(/\./g, '/').indexOf(file.substring(0,file.lastIndexOf("/")).replace("src/", '')) != -1){1268 found = true;1269 var parsedLineNumber = (parseInt(lineNumber,10)-1).toString();1270 newTrace += ",\r\n<a style= 'color: blue;' href='javascript:openScript(""+ file +"",""+ parsedLineNumber +"")'>" + line +"</a>";1271 }1272 }1273 count++;1274 if (count == sourceCache.length){1275 if (found == false){1276 if (line.indexOf("[") == 0){1277 newTrace += line;1278 }1279 else{1280 newTrace += ",\r\n"+line;1281 }1282 }1283 if (traceCount == traces.length){1284 callback(newTrace);1285 }1286 }1287 });1288 }1289 else{1290 if (traceCount == traces.length){1291 callback(newTrace);1292 }1293 }1294 });1295}1296function markFinishedResults(results,sourceCache,callback){1297 var count = 0;1298 var result = "Passed";1299 var status = "Finished";1300 results.forEach(function(action){1301 if (action.status == "Not Run"){1302 if (action.children.length != 0){1303 markFinishedResults(action.children,sourceCache,function(childStatus,childResult,markFinished){1304 action.expanded = false;1305 if (markFinished === true){1306 action.status = "Finished";1307 action.result = "Failed";1308 action.expanded = true;1309 callback("Finished","Failed",true);1310 return;1311 }1312 count++;1313 if (childStatus == "Not Run"){1314 status = "Not Run";1315 result = "";1316 }1317 if((childStatus == "Finished") && (childResult == "Failed")){1318 result = "Failed";1319 action.expanded = true;1320 }1321 if(count == action.children.length){1322 action.result = result;1323 action.status = status;1324 if (status == "Finished"){1325 if ((action.executionflow == "Record Error Stop Test Case")&&(result == "Failed")){1326 callback(status,result,true)1327 }1328 else{1329 callback(status,result)1330 }1331 }1332 else{1333 callback(status,"")1334 }1335 }1336 })1337 }1338 else{1339 callback("Not Run","")1340 }1341 }1342 else{1343 var returnValue;1344 if ((action.executionflow == "Record Error Stop Test Case")&&(action.result == "Failed")){1345 returnValue = function(){callback("Finished","Failed",true)}1346 }1347 else{1348 returnValue = function(){callback("Finished",action.result)}1349 }1350 if(action.result == "Failed"){1351 action.expanded = true;1352 }1353 if(action.trace){1354 formatTrace(action.trace,sourceCache,function(trace){1355 if(trace != "") action.trace = trace;1356 returnValue();1357 })1358 }1359 else{1360 returnValue();1361 }1362 }1363 });1364}1365exports.agentBaseState = function(project,executionID,agentHost,port,threadID,callback){agentBaseState(project,executionID,agentHost,port,threadID,callback)};1366function agentBaseState(project,executionID,agentHost,port,threadID,callback){1367 common.logger.info("__dirname:"+path.resolve(__dirname,"../agent/executionfiles/"+executionID));1368 //copyFile(path.join(__dirname, "../public/automationscripts/"+project+"/build/jar"+projectUser+".jar"),path.join(__dirname, "../agent/executionfiles/lib"),callback());1369 //sendFileToAgent((path.join(__dirname, "../public/automationscripts/"+project+"/build/jar").toString())+projectUser+".jar","executionfiles/lib",agentHost,port,3,callback());1370 //fs.exists(path.resolve(__dirname,"../agent/executionfiles/"+executionID+"/lib"), function (exists) {1371 fs.exists(path.resolve(__dirname,"../agent/executionfiles/lib"), function (exists) {1372 if(exists == false){1373 sendAgentCommand(agentHost,port,{command:"cleanup",executionID:executionID},3,function(message){1374 if (message.error){1375 callback(message.error);1376 return;1377 }1378 //syncFilesWithAgent(agentHost,port,path.join(__dirname, '../public/automationscripts/'+project+"/bin"),"executionfiles/"+executionID+"/bin",function(error){1379 syncFilesWithAgent(agentHost,port,path.join(__dirname, '../public/automationscripts/'+project+"/bin"),"executionfiles/bin",function(error){1380 if(error) {callback(error);return}1381 //syncFilesWithAgent(agentHost,port,path.join(__dirname, '../launcher'),"executionfiles/"+executionID+"/launcher",function(){1382 syncFilesWithAgent(agentHost,port,path.join(__dirname, '../launcher'),"executionfiles/launcher",function(){1383 //syncFilesWithAgent(agentHost,port,path.join(__dirname, '../public/automationscripts/'+project+"/External Libraries"),"executionfiles/"+executionID+"/lib",function(){1384 syncFilesWithAgent(agentHost,port,path.join(__dirname, '../public/automationscripts/'+project+"/External Libraries"),"executionfiles/lib",function(){1385 //syncFilesWithAgent(agentHost,port,path.join(__dirname, '../public/automationscripts/'+project+"/build/jar_"+executionID),"executionfiles/"+executionID+"/lib",function(){1386 //syncFilesWithAgent(agentHost,port,os.tmpDir()+"/jar_"+executionID,"executionfiles/"+executionID+"/lib",function(){1387 syncFilesWithAgent(agentHost,port,os.tmpDir()+"/jar_"+executionID,"executionfiles/lib",function(){1388 syncFilesWithAgent(agentHost,port,path.join(__dirname, '../public/automationscripts/'+project+"/build/jar/projectJar"),"executionfiles/lib",function(){1389 common.logger.info("synced all files with agent");1390 sendAgentCommand(agentHost,port,{command:"start launcher",executionID:executionID,threadID:threadID},3,function(message){1391 common.logger.info("inside sendAgentCommand");1392 if ((message) && (message.error)){1393 common.logger.info("sendAgentCommand error: " & message.error)1394 callback(message.error);1395 }1396 else{1397 common.logger.info("sendAgentCommand no error")1398 callback();1399 }1400 });1401 })1402 })1403 })1404 })1405 });1406 });1407 }1408 else{1409 syncFilesWithAgent(agentHost,port,path.join(__dirname, '../public/automationscripts/'+project+"/build/jar/projectJar"),"executionfiles/lib",function(){1410 sendAgentCommand(agentHost,port,{command:"start launcher",executionID:executionID,threadID:threadID},3,function(message){1411 common.logger.info("inside sendAgentCommand");1412 if ((message) && (message.error)){1413 common.logger.info("sendAgentCommand error: " & message.error)1414 callback(message.error);1415 }1416 else{1417 common.logger.info("sendAgentCommand no error")1418 callback();1419 }1420 });1421 });1422 }1423 });1424 /*sendAgentCommand(agentHost,port,{command:"start launcher",executionID:executionID,threadID:threadID},3,function(message){1425 common.logger.info("inside sendAgentCommand");1426 if ((message) && (message.error)){1427 common.logger.info("sendAgentCommand error: " & message.error)1428 callback(message.error);1429 }1430 else{1431 common.logger.info("sendAgentCommand no error")1432 callback();1433 }1434 });*/1435}1436function syncFilesWithAgent_old(agentHost,port,rootPath,destDir,callback){1437 var walker = walk.walkSync(rootPath);1438 var fileCount = 0;1439 walker.on("file", function (root, fileStats, next) {1440 fileCount++;1441 var path = root.replace(rootPath,"");1442 var dest = "";1443 if (path == ""){1444 dest = destDir +"/"+ fileStats.name;1445 }1446 else{1447 dest = destDir + path+"/"+fileStats.name1448 }1449 sendFileToAgent(root+"/"+fileStats.name,dest,agentHost,port,3,function(){1450 fileCount--;1451 if(fileCount == 0){1452 callback();1453 }1454 });1455 });1456 walker.on("end",function(){1457 if (fileCount == 0) callback();1458 });1459}1460function syncFilesWithAgent(agentHost,port,rootPath,destDir,callback){1461 var walker = walk.walkSync(rootPath);1462 var fileCount = 0;1463 var files = [];1464 var foundError = false;1465 var sendFiles = function(){1466 if(foundError) return;1467 fileCount++;1468 if (!files[fileCount-1]){1469 callback();1470 return;1471 }1472 sendFileToAgent(files[fileCount-1].file,files[fileCount-1].dest,agentHost,port,3,function(error){1473 if(error){1474 foundError = true;1475 callback(error);1476 return;1477 }1478 if(fileCount === files.length){1479 callback();1480 }1481 else{1482 sendFiles()1483 }1484 });1485 };1486 walker.on("file", function (root, fileStats, next) {1487 var path = root.replace(rootPath,"");1488 var dest = "";1489 if (path == ""){1490 dest = destDir +"/"+ fileStats.name;1491 }1492 else{1493 dest = destDir + path+"/"+fileStats.name1494 }1495 files.push({file:root+"/"+fileStats.name,dest:dest});1496 });1497 walker.on("end",function(){1498 sendFiles()1499 });1500}1501function sendFileToAgent(file,dest,agentHost,port,retryCount,callback){1502 var stat = fs.statSync(file);1503 1504 common.logger.info("file: "+file);1505 common.logger.info("dest: "+dest);1506 var readStream = fs.createReadStream(file);1507 var boundary = '--------------------------';1508 for (var i = 0; i < 24; i++) {1509 boundary += Math.floor(Math.random() * 10).toString(16);1510 }1511 var message = '------' + boundary + '\r\n'1512 // use your file's mime type here, if known1513 + 'Content-Disposition: form-data; name="file"; filename="'+dest+'"\r\n'1514 + 'Content-Type: application/octet-stream\r\n'1515 // "name" is the name of the form field1516 // "filename" is the name of the original file1517 + 'Content-Transfer-Encoding: binary\r\n\r\n';1518 var options = {1519 hostname: agentHost,1520 port: port,1521 path: '/fileupload',1522 method: 'POST',1523 headers: {1524 //'Content-Type': 'text/plain'//,1525 'Content-Type': 'multipart/form-data; boundary=----'+boundary,1526 //'Content-Disposition': 'form-data; name="file"; filename="ProjectName.jar"',1527 //'Content-Length': 33601528 //'Content-Length': stat.size + message.length + 30 + boundary.length1529 'Content-Length': stat.size + message.length + boundary.length + 141530 }1531 };1532 var req = http.request(options, function(res) {1533 //res.setEncoding('utf8');1534 res.on('data', function (chunk) {1535 if (callback) callback();1536 });1537 });1538 req.on('error', function(e) {1539 if(retryCount <= 0){1540 if (callback) callback({error:'sendFileToAgent problem with request: ' + e.message+ ' file:'+file});1541 common.logger.error('sendFileToAgent problem with request: ' + e.message+ ' file:'+file);1542 }1543 else{1544 retryCount--;1545 setTimeout(sendFileToAgent(file,dest,agentHost,port,retryCount,callback),1000)1546 }1547 });1548 req.write(message);1549 readStream.pipe(req, { end: false });1550 readStream.on("end", function(){1551 req.end('\r\n------' + boundary + '--\r\n');1552 });1553}1554exports.sendAgentCommand = function(agentHost,port,command,retryCount,callback){sendAgentCommand(agentHost,port,command,retryCount,callback)};1555function sendAgentCommand(agentHost,port,command,retryCount,callback){1556 common.logger.info(command);1557 var options = {1558 hostname: agentHost,1559 port: port,1560 path: '/command',1561 method: 'POST',1562 headers: {1563 'Content-Type': 'application/json'1564 }1565 };1566 var req = http.request(options, function(res) {1567 res.setEncoding('utf8');1568 res.on('data', function (chunk) {1569 try{1570 var msg = JSON.parse(chunk);1571 }1572 catch(err){1573 if (callback) callback(err);1574 }1575 if((msg )&&(msg.error != null)){1576 if (callback) callback(msg.error);1577 }1578 else if (msg){1579 if(callback) callback(msg);1580 }1581 else{1582 if(callback) callback();1583 }1584 });1585 });1586 req.setTimeout(50000, function(){1587 //when timeout, this callback will be called1588 });1589 req.on('error', function(e) {1590 retryCount = 0;1591 if(retryCount <= 0){1592 if (callback) callback("Unable to connect to machine: "+agentHost + " error: " + e.message);1593 common.logger.error('sendAgentCommand problem with request: ' + e.message+ ' ');1594 }1595 else{1596 retryCount--;1597 setTimeout(sendAgentCommand(agentHost,port,command,retryCount,callback),1000)1598 }1599 });1600 // write data to request body1601 req.write(JSON.stringify(command));1602 req.end();1603}1604function resolveParamValue(value,variables){1605 var returnNULL = false;1606 if(Object.prototype.toString.call(value) == '[object Array]'){1607 if((value.length == 1) && (value[0] === "<NULL>")){1608 return [];1609 }1610 else{1611 return value;...
executionengine.js
Source:executionengine.js
...374 }375 newMachine.threadID = i+startThread-1;376 common.logger.info(newMachine);377 executions[executionID].machines.push(newMachine);378 sendAgentCommand(newMachine.host,newMachine.port,{command:"start launcher",executionID:executionID,threadID:newMachine.threadID},3,function(err){379 newMachineCount++;380 if (newMachineCount == machine.threads){381 count++;382 if(count == mainMachinesCount){383 callback();384 }385 }386 });387 }388 });389 }390 else{391 count++;392 if(count == mainMachinesCount){393 callback();394 }395 }396 });397 });398 });399}400function suiteBaseState(executionID,machines,callback){401 var count = 0;402 var foundSuiteState = false;403 var suiteBaseTCs = [];404 var lastMachine = function(){405 if (count === machines.length){406 if (suiteBaseTCs.length > 0){407 executions[executionID].cachedTCs = executions[executionID].testcases;408 executions[executionID].testcases = {};409 suiteBaseTCs.forEach(function(tc){410 executions[executionID].testcases[tc.testcaseID] = tc;411 });412 executions[executionID].baseStateFailed = false;413 }414 callback()415 }416 };417 machines.forEach(function(machine){418 if(machine.baseState){419 foundSuiteState = true;420 machine.roles.push(machine.host);421 db.collection('testcases', function(err, collection) {422 collection.insert({baseState:true,name:machine.host+"_state",status:"Automated",type:"collection",collection:[{order:"1",actionid:machine.baseState,host:machine.host,executionflow:"Record Error Stop Test Case",parameters:[]}]}, {safe:true},function(err,testcaseData){423 db.collection('executiontestcases', function(err, collection) {424 //collection.save({_id:machine.resultID},{},{$set:{executionID:executionID,name:machine.host+"_state",status:"Not Run",testcaseID:testcaseData[0]._id.__id,_id: machine.resultID}}, {safe:true,new:true},function(err,returnData){425 collection.save({baseState:true,executionID:executionID,name:machine.host+"_state",status:"Not Run",testcaseID:testcaseData[0]._id.__id,_id: machine.baseStateTCID},function(err,returnData){426 suiteBaseTCs.push({testcaseID:testcaseData[0]._id.__id,retryCount:0,_id:machine.baseStateTCID,status:"Not Run",name:machine.host+"_state",type:"collection"});427 count++;428 lastMachine();429 });430 });431 });432 });433 }434 else{435 count++;436 }437 lastMachine();438 });439}440exports.cacheSourceCode = function(rootPath,callback){cacheSourceCode(rootPath,callback)};441function cacheSourceCode(rootPath,callback){442 git.lsFiles(rootPath,["*.groovy","*.java"],function(data){443 var files = [];444 if ((data != "")&&(data.indexOf("\n") != -1)){445 files = data.split("\n",data.match(/\n/g).length);446 }447 callback(files);448 })449}450function getGlobalVars(executionID,callback){451 db.collection('variables', function(err, collection) {452 collection.find({taskVar:false}, {}, function(err, cursor) {453 cursor.each(function(err, variable) {454 if(variable == null) {455 callback();456 }457 else{458 executions[executionID].variables[variable.name] = variable.value;459 }460 });461 })462 });463}464function cleanUpMachines(machines,executionID,callback){465 var count = 0;466 machines.forEach(function(machine){467 sendAgentCommand(machine.host,machine.port,{command:"cleanup",executionID:executionID},3,function(err){468 count++;469 if(count == machines.length){470 if(callback) callback();471 }472 });473 })474}475function executeTestCases(testcases,executionID){476 if (!executions[executionID]) return;477 executions[executionID].executingTCs = true;478 var variables = executions[executionID].variables;479 var machines = executions[executionID].machines;480 var tcArray = [];481 for(var key in testcases){482 tcArray.push(key);483 }484 //execution all done485 //if (tcArray.length == 0){486 var finishExecution = function(callback){487 if (executions[executionID].cachedTCs){488 if(executions[executionID].baseStateFailed === true){489 unlockCloudMachines(executions[executionID].machines);490 unlockMachines(machines,function(){491 cleanUpMachines(executions[executionID].machines,executionID,function(){492 });493 updateExecution({_id:executionID},{$set:{status:"Ready To Run"}},true,function(){494 executionsRoute.updateExecutionTotals(executionID,function(){495 if(executions[executionID].sendEmail == true) sendNotification(executionID);496 //git.deleteFiles(path.join(__dirname, '../public/automationscripts/'+executions[executionID].project+"/"+executions[executionID].username+"/build"),os.tmpDir()+"/jar_"+executionID);497 deleteDir(os.tmpDir()+"/jar_"+executionID);498 delete executions[executionID];499 });500 });501 callback(true)502 });503 return;504 }505 executions[executionID].machines.forEach(function(machine){506 machine.baseState = null;507 });508 executions[executionID].testcases = executions[executionID].cachedTCs;509 delete executions[executionID].cachedTCs;510 tcArray = [];511 for(key in executions[executionID].testcases){512 tcArray.push(key);513 }514 testcases = executions[executionID].testcases;515 callback(false)516 }517 else{518 if(executions[executionID]){519 unlockCloudMachines(executions[executionID].machines);520 unlockMachines(executions[executionID].machines,function(){521 cleanUpMachines(executions[executionID].machines,executionID,function(){522 });523 updateExecution({_id:executionID},{$set:{status:"Ready To Run"}},true,function(){524 executionsRoute.updateExecutionTotals(executionID,function(){525 if(executions[executionID].sendEmail == true) sendNotification(executionID);526 //git.deleteFiles(path.join(__dirname, '../public/automationscripts/'+executions[executionID].project+"/"+executions[executionID].username+"/build"),os.tmpDir()+"/jar_"+executionID);527 deleteDir(os.tmpDir()+"/jar_"+executionID);528 delete executions[executionID];529 });530 });531 callback(true)532 });533 }534 //return;535 }536 };537 var count = 0;538 var doneCount = 0;539 var nextTC = function(){540 if (!testcases[tcArray[count]]){541 executions[executionID].executingTCs = false;542 return;543 }544 if (testcases[tcArray[count]].executing == true){545 count++;546 nextTC();547 return;548 }549 else if(testcases[tcArray[count]].finished == true){550 count++;551 doneCount++;552 if (doneCount == tcArray.length){553 finishExecution(function(finishIt){554 if(finishIt == false){555 count = 0;556 nextTC();557 }558 else{559 if(executions[executionID]) executions[executionID].executingTCs = false;560 }561 });562 return;563 }564 nextTC();565 return;566 }567 testcases[tcArray[count]].executing = true;568 startTCExecution(testcases[tcArray[count]].testcaseID,variables,executionID,function(){569 if (!executions[executionID]) return;570 count++;571 var machineAvailable = false;572 machines.forEach(function(machine){573 if(machine.runningTC == undefined){574 machineAvailable = true;575 }576 });577 if((count < tcArray.length)&&(machineAvailable == true)){578 nextTC();579 }580 else{581 executions[executionID].executingTCs = false;582 //remove any useless machines583 var toRemove = [];584 machines.forEach(function(machine){585 if(machine.runningTC == undefined){586 //don't remove any machines if this is just a suite base state that is running587 if(!executions[executionID].cachedTCs){588 toRemove.push(machine)589 }590 }591 });592 unlockMachines(toRemove,function(){593 toRemove.forEach(function(machine){594 machines.splice(machines.indexOf(machine),1);595 });596 });597 //if nothing else to execute finish it.598 var somethingToRun = false;599 tcArray.forEach(function(testcaseCount){600 if(testcases[testcaseCount].finished != true){601 somethingToRun = true;602 }603 });604 if(somethingToRun == false){605 finishExecution(function(finishIt){606 if(finishIt == false){607 count = 0;608 nextTC();609 }610 else{611 if(executions[executionID]) executions[executionID].executingTCs = false;612 }613 });614 }615 }616 });617 };618 if (count == 0) nextTC();619}620function startTCExecution(id,variables,executionID,callback){621 GetTestCaseDetails(id,executionID,function(testcase,result,hosts){622 if(testcase == null){623 callback();624 return;625 }626 testcase.machines = [];627 testcase.machineVars = [];628 var reservedHosts = [];629 var busyMachines = false;630 executions[executionID].machines.forEach(function(machine,index){631 if(machine.runningTC != undefined){632 busyMachines = true;633 }634 hosts.forEach(function(host){635 if((machine.roles.indexOf(host) != -1)&& (reservedHosts.indexOf(host) == -1) &&((machine.runningTC == undefined)||(machine.runningTC == testcase))){636 machine.runningTC = testcase;637 reservedHosts.push(host);638 testcase.machines.push(machine);639 machine.roles.forEach(function(role){640 if (machine.machineVars){641 machine.machineVars.forEach(function(variable){642 testcase.machineVars["Machine."+role+"."+variable.name] = variable.value643 });644 }645 testcase.machineVars["Machine."+role+".Host"] = machine.host;646 testcase.machineVars["Machine."+role+".Port"] = machine.port;647 })648 }649 });650 });651 if ((testcase.machines.length == 0) || (reservedHosts.length != hosts.length)){652 if(busyMachines == true){653 executions[executionID].testcases[id].executing = false;654 callback();655 return;656 }657 }658 result.status = "Running";659 createResult(result,function(writtenResult){660 result._id = writtenResult[0]._id;661 result.executionID = executionID;662 executions[executionID].currentTestCases[testcase.dbTestCase._id] = {testcase:testcase,result:result,executionTestCaseID:id};663 //testcase.machines = [];664 testcase.startDate = new Date();665 if (((testcase.dbTestCase.status != "Automated")||(testcase.statusError)) && (executions[executionID].ignoreStatus == false)){666 var error = "";667 if (testcase.statusError){668 error = testcase.statusError669 }else if(testcase.dbTestCase.status == "To be Automated"){670 error = "Test Case is not Automated"671 }else if(testcase.dbTestCase.status == "Needs Maintenance"){672 error = "Test Case Needs Maintenance"673 }674 //if (callback){675 // callback({error:error});676 //}677 result.error = testcase.dbTestCase.status;678 result.status = "Not Run";679 //result.result = testcase.dbTestCase.status;680 result.result = error;681 updateResult(result);682 //executions[executionID].testcases[id].result = result;683 finishTestCaseExecution(executions[executionID],executionID,executions[executionID].testcases[id]._id,executions[executionID].currentTestCases[testcase.dbTestCase._id]);684 callback();685 return;686 }687 //if there is nothing to execute just finish the TC688 if (((testcase.dbTestCase.type === "collection")&&(testcase.actions.length == 0)) || ((testcase.dbTestCase.type === "script")&&(testcase.dbTestCase.script == ""))){689 //if (callback){690 // callback();691 //}692 result.status = "Finished";693 result.result = "Passed";694 updateResult(result);695 finishTestCaseExecution(executions[executionID],executionID,executions[executionID].testcases[id]._id,executions[executionID].currentTestCases[testcase.dbTestCase._id]);696 callback();697 return;698 }699 //updateExecutionTestCase({_id:testcases[0]._id.executionTestCaseID},{$set:{"status":"Running"}});700 var machines = executions[executionID].machines;701 machines.sort(function(a,b){702 return a.roles.length - b.roles.length;703 });704 /*705 var reservedHosts = [];706 testcase.machines = [];707 testcase.machineVars = [];708 machines.forEach(function(machine,index){709 hosts.forEach(function(host){710 if((machine.roles.indexOf(host) != -1)&& (reservedHosts.indexOf(host) == -1) &&((machine.runningTC == undefined)||(machine.runningTC == testcase))){711 machine.runningTC = testcase;712 reservedHosts.push(host);713 testcase.machines.push(machine);714 machine.roles.forEach(function(role){715 if (machine.machineVars){716 machine.machineVars.forEach(function(variable){717 testcase.machineVars["Machine."+role+"."+variable.name] = variable.value718 });719 }720 testcase.machineVars["Machine."+role+".Host"] = machine.host;721 testcase.machineVars["Machine."+role+".Port"] = machine.port;722 })723 }724 });725 });726 */727 if ((testcase.machines.length == 0) || (reservedHosts.length != hosts.length)){728 //if (callback){729 // callback({error:"Unable to find matching machine for this test case. Roles required are:"+hosts.join()});730 //}731 //updateExecutionTestCase({_id:executions[executionID].testcases[id]._id},{$set:{"status":"Finished",result:"Failed",resultID:result._id,error:"Unable to find matching machine for this test case. Roles required are:"+hosts.join()}});732 result.error = "Unable to find matching machine for this test case. Roles required are:"+hosts.join();733 result.status = "Finished";734 result.result = "Failed";735 updateResult(result);736 finishTestCaseExecution(executions[executionID],executionID,executions[executionID].testcases[id]._id,executions[executionID].currentTestCases[testcase.dbTestCase._id]);737 callback();738 return;739 }740 var count = 0;741 var errorFound = false;742 //var startTC = function(){743 var agentInstructions = {command:"run action",executionID:executionID,testcaseID:testcase.dbTestCase._id,variables:executions[executionID].variables};744 var foundMachine = null;745 var runBaseState = function(){746 agentBaseState(executions[executionID].project+"/"+executions[executionID].username,executionID,foundMachine.host,foundMachine.port,foundMachine.threadID,function(err){747 if (err){748 result.error = err.error;749 result.status = "Finished";750 result.result = "Failed";751 updateResult(result);752 if (executions[executionID]){753 executions[executionID].currentTestCases[testcase.dbTestCase._id].result = result;754 finishTestCaseExecution(executions[executionID],executionID,executions[executionID].testcases[id]._id,executions[executionID].currentTestCases[testcase.dbTestCase._id]);755 }756 }757 else{758 foundMachine.runBaseState = true;759 sendAgentCommand(foundMachine.host,foundMachine.port,agentInstructions,3);760 }761 });762 };763 //if test case is a script and NOT an action collection764 if (testcase.dbTestCase.type !== "collection"){765 if ((testcase.script == "") || (!testcase.script)){766 result.error = "Test Case does not have a script assigned";767 result.status = "Finished";768 result.result = "Failed";769 updateResult(result);770 //executions[executionID].testcases[id].result = result;771 finishTestCaseExecution(executions[executionID],executionID,executions[executionID].testcases[id]._id,executions[executionID].currentTestCases[testcase.dbTestCase._id]);772 return;773 }774 agentInstructions.name = testcase.name;775 agentInstructions.ignoreScreenshots = executions[executionID].ignoreScreenshots;776 agentInstructions.allScreenshots = executions[executionID].allScreenshots;777 agentInstructions.executionID = executionID;778 agentInstructions.testcaseName = testcase.name;779 agentInstructions.script = testcase.script;780 agentInstructions.scriptLang = testcase.scriptLang;781 agentInstructions.resultID = result._id.__id;782 agentInstructions.parameters = [];783 agentInstructions.type = testcase.dbTestCase.type;784 var actionHost = "Default";785 //if(action.dbAction.host != "") actionHost = action.dbAction.host;786 testcase.machines.forEach(function(machine){787 if ((machine.roles.indexOf(actionHost) != -1)&&(foundMachine == null)){788 foundMachine = machine;789 }790 });791 agentInstructions.threadID = foundMachine.threadID;792 updateExecutionTestCase({_id:executions[executionID].testcases[id]._id},{$set:{"status":"Running","result":"",error:"",trace:"",resultID:result._id,startdate:testcase.startDate,enddate:"",runtime:"",host:foundMachine.host,vncport:foundMachine.vncport}},foundMachine.host,foundMachine.vncport);793 executionsRoute.updateExecutionTotals(executionID);794 if (foundMachine.runBaseState === true){795 if (foundMachine.multiThreaded == true){796 sendAgentCommand(foundMachine.host,foundMachine.port,agentInstructions,3);797 }798 else{799 //make sure the files are actually there, in case of revert to snapshot or not persistent VMs files800 //could have changed while test case was running801 sendAgentCommand(foundMachine.host,foundMachine.port,{command:"files loaded",executionID:executionID},3,function(message){802 if (message.loaded == true){803 sendAgentCommand(foundMachine.host,foundMachine.port,agentInstructions,3);804 }805 else{806 runBaseState();807 }808 });809 }810 }811 else{812 runBaseState();813 }814 callback();815 return;816 }817 callback();818 for (var attrname in testcase.machineVars) { variables[attrname] = testcase.machineVars[attrname]; }819 variables["Framework.TestCaseName"] = testcase.dbTestCase.name;820 findNextAction(testcase.actions,variables,function(action){821 if (!executions[executionID]) return;822 if(!executions[executionID].currentTestCases[testcase.dbTestCase._id]) return;823 if(action == null){824 finishTestCaseExecution(executions[executionID],executionID,executions[executionID].testcases[id]._id,executions[executionID].currentTestCases[testcase.dbTestCase._id]);825 return;826 }827 executions[executionID].currentTestCases[testcase.dbTestCase._id].currentAction = action;828 agentInstructions.name = action.name;829 agentInstructions.executionflow = action.dbAction.executionflow;830 agentInstructions.executionID = executionID;831 agentInstructions.ignoreScreenshots = executions[executionID].ignoreScreenshots;832 agentInstructions.allScreenshots = executions[executionID].allScreenshots;833 agentInstructions.returnValueName = action.dbAction.returnvalue;834 agentInstructions.testcaseName = testcase.dbTestCase.name;835 agentInstructions.script = action.script;836 agentInstructions.scriptLang = action.scriptLang;837 agentInstructions.resultID = result._id.__id;838 agentInstructions.parameters = [];839 action.dbAction.parameters.forEach(function(parameter){840 agentInstructions.parameters.push({name:parameter.paramname,value:parameter.paramvalue});841 });842 var actionHost = "Default";843 if(action.dbAction.host != "") actionHost = action.dbAction.host;844 testcase.machines.forEach(function(machine){845 if ((machine.roles.indexOf(actionHost) != -1)&&(foundMachine == null)){846 foundMachine = machine;847 }848 });849 agentInstructions.threadID = foundMachine.threadID;850 updateExecutionTestCase({_id:executions[executionID].testcases[id]._id},{$set:{"status":"Running","result":"",error:"",trace:"",resultID:result._id,startdate:testcase.startDate,enddate:"",runtime:"",host:foundMachine.host,vncport:foundMachine.vncport}},foundMachine.host,foundMachine.vncport);851 if ((testcase.machines.length > 0) &&((testcase.machines[0].baseState))){852 updateExecutionMachine(executionID,testcase.machines[0]._id,"",result._id.__id);853 }854 executionsRoute.updateExecutionTotals(executionID);855 if (foundMachine.runBaseState === true){856 if (foundMachine.multiThreaded == true){857 sendAgentCommand(foundMachine.host,foundMachine.port,agentInstructions,3);858 }859 else{860 //make sure the files are actually there, in case of revert to snapshot or not persistent VMs files861 //could have changed while test case was running862 sendAgentCommand(foundMachine.host,foundMachine.port,{command:"files loaded",executionID:executionID},3,function(message){863 if (message.loaded == true){864 sendAgentCommand(foundMachine.host,foundMachine.port,agentInstructions,3);865 }866 else{867 runBaseState();868 }869 });870 }871 }872 else{873 runBaseState();874 }875 });876 })877 });878}879exports.logPost = function(req,res){880 var record = req.body;881 var executionID = record.executionID.replace(/-/g, '');882 delete record.command;883 delete record.executionID;884 db.collection('executionlogs'+executionID, function(err, collection) {885 collection.insert(record, {safe:true},function(err,returnData){886 res.contentType('json');887 res.json({success:true});888 realtime.emitMessage("AddExecutionLog",record);889 });890 });891};892exports.actionresultPost = function(req, res){893 res.contentType('json');894 res.json({success:true});895 var execution = executions[req.body.executionID];896 if (!execution) return;897 var testcase = execution.currentTestCases[req.body.testcaseID];898 if (testcase == undefined) return;899 if (testcase.testcase.script){900 testcase.result.status = "Finished";901 testcase.result.result = req.body.result;902 if (req.body.error){903 testcase.result.error = req.body.error;904 }905 else{906 testcase.result.error = "";907 }908 if (req.body.trace){909 formatTrace(req.body.trace,execution.sourceCache,function(trace){910 testcase.result.trace = trace;911 if(trace == "") testcase.result.trace = req.body.trace;912 updateResult(testcase.result);913 });914 }915 else{916 updateResult(testcase.result);917 }918 finishTestCaseExecution(execution,req.body.executionID,execution.testcases[testcase.executionTestCaseID]._id,testcase);919 return;920 }921 testcase.currentAction.result.status = "Finished";922 testcase.currentAction.result.result = req.body.result;923 if(!testcase.result.error){924 testcase.result.error = "";925 }926 if (req.body.error){927 testcase.result.error = req.body.error;928 testcase.currentAction.result.error = req.body.error;929 }930 if (req.body.trace){931 testcase.result.trace = req.body.trace;932 testcase.currentAction.result.trace = req.body.trace;933 testcase.trace = req.body.trace;934 }935 if (req.body.screenshot){936 testcase.result.screenshot = req.body.screenshot;937 testcase.currentAction.result.screenshot = req.body.screenshot;938 }939 if ((req.body.returnValue)&&(testcase.currentAction.dbAction.returnvalue != "")){940 if(!execution.returnVars[req.body.testcaseID]){941 execution.returnVars[req.body.testcaseID] = {};942 }943 execution.returnVars[req.body.testcaseID][testcase.currentAction.dbAction.returnvalue] = req.body.returnValue;944 //.[testcase.currentAction.dbAction.returnvalue] = req.body.returnValue;945 //execution.variables[testcase.currentAction.dbAction.returnvalue] = req.body.returnValue;946 }947 var actionFlow = testcase.currentAction.dbAction.executionflow;948 if (req.body.result == "Failed"){949 if (actionFlow == "Record Error Stop Test Case"){950 testcase.result.status = "Finished";951 testcase.result.result = "Failed";952 testcase.runAfterState = true;953 testcase.testcase.actions.forEach(function(action){954 if(!action.dbAction.afterState == true){955 action.runAction = false;956 }957 });958 //updateExecutionTestCase({_id:execution.testcases[testcase.executionTestCaseID]._id},{$set:{error:testcase.result.error,trace:testcase.trace}});959 /*960 markFinishedResults(testcase.result.children,execution.sourceCache,function(){961 updateResult(testcase.result);962 });963 finishTestCaseExecution(execution,req.body.executionID,execution.testcases[testcase.executionTestCaseID]._id,testcase);964 return;965 */966 }967 else if (actionFlow == "Record Error Continue Test Case"){968 testcase.result.result = "Failed";969 updateExecutionTestCase({_id:execution.testcases[testcase.executionTestCaseID]._id},{$set:{result:"Failed",trace:testcase.trace}});970 }971 else{972 testcase.currentAction.result.result = "";973 testcase.currentAction.result.trace = "";974 testcase.currentAction.result.error = "";975 testcase.result.result = "";976 testcase.result.error = "";977 }978 }979 markFinishedResults(testcase.result.children,execution.sourceCache,function(){980 updateResult(testcase.result);981 });982 var actionVariables = {};983 for (var attrname in execution.variables) { actionVariables[attrname] = execution.variables[attrname]; }984 for (var attrname in testcase.machineVars) { actionVariables[attrname] = testcase.machineVars[attrname]; }985 if(execution.returnVars[testcase.executionTestCaseID]){986 for (var attrname in execution.returnVars[testcase.executionTestCaseID]) { actionVariables[attrname] = execution.returnVars[testcase.executionTestCaseID][attrname]; }987 }988 findNextAction(testcase.testcase.actions,actionVariables,function(action){989 if(action == null){990 testcase.result.status = "Finished";991 if(testcase.result.result != "Failed") testcase.result.result = "Passed";992 updateResult(testcase.result);993 finishTestCaseExecution(execution,req.body.executionID,execution.testcases[testcase.executionTestCaseID]._id,testcase);994 return;995 }996 var foundMachine = null;997 var actionHost = "Default";998 if(action.dbAction.host != "") actionHost = action.dbAction.host;999 testcase.testcase.machines.forEach(function(machine){1000 if ((machine.roles.indexOf(actionHost) != -1)&&(foundMachine == null)){1001 foundMachine = machine;1002 }1003 });1004 updateExecutionTestCase({_id:execution.testcases[testcase.executionTestCaseID]._id},{$set:{"status":"Running","result":"",host:foundMachine.host,vncport:foundMachine.vncport}},foundMachine.host,foundMachine.vncport);1005 testcase.result.status = "Running";1006 var agentInstructions = {command:"run action",executionID:req.body.executionID,threadID:foundMachine.threadID,testcaseID:testcase.testcase.dbTestCase._id,variables:execution.variables};1007 execution.currentTestCases[testcase.testcase.dbTestCase._id].currentAction = action;1008 agentInstructions.name = action.name;1009 agentInstructions.executionflow = action.dbAction.executionflow;1010 agentInstructions.executionID = req.body.executionID;1011 agentInstructions.ignoreScreenshots = executions[req.body.executionID].ignoreScreenshots;1012 agentInstructions.allScreenshots = executions[req.body.executionID].allScreenshots;1013 agentInstructions.returnValueName = action.dbAction.returnvalue;1014 agentInstructions.testcaseName = testcase.testcase.dbTestCase.name;1015 agentInstructions.script = action.script;1016 agentInstructions.scriptLang = action.scriptLang;1017 agentInstructions.resultID = testcase.result._id.__id;1018 agentInstructions.parameters = [];1019 action.dbAction.parameters.forEach(function(parameter){1020 agentInstructions.parameters.push({name:parameter.paramname,value:parameter.paramvalue});1021 });1022 var runBaseState = function(){1023 agentBaseState(execution.project+"/"+execution.username,req.body.executionID,foundMachine.host,foundMachine.port,foundMachine.threadID,function(err){1024 if (err){1025 testcase.result.error = err.error;1026 testcase.result.status = "Finished";1027 testcase.result.result = "Failed";1028 updateResult(testcase.result);1029 if (execution){1030 execution.currentTestCases[testcase.dbTestCase._id].result = "Failed";1031 finishTestCaseExecution(execution,req.body.executionID,execution.testcases[id]._id,execution.currentTestCases[testcase.dbTestCase._id]);1032 }1033 }1034 else{1035 foundMachine.runBaseState = true;1036 sendAgentCommand(foundMachine.host,foundMachine.port,agentInstructions,3);1037 }1038 });1039 };1040 if (foundMachine.runBaseState === true){1041 if (foundMachine.multiThreaded == true){1042 sendAgentCommand(foundMachine.host,foundMachine.port,agentInstructions,3);1043 }1044 else{1045 //make sure the files are actually there, in case of revert to snapshot or not persistent VMs files1046 //could have changed while test case was running1047 sendAgentCommand(foundMachine.host,foundMachine.port,{command:"files loaded",executionID:req.body.executionID},3,function(message){1048 if (message.loaded == true){1049 sendAgentCommand(foundMachine.host,foundMachine.port,agentInstructions,3);1050 }1051 else{1052 runBaseState();1053 }1054 });1055 }1056 }1057 else{1058 runBaseState();1059 }1060 });1061};1062//last action or we are done with the TC1063//start next test case if there is one1064function finishTestCaseExecution(execution,executionID,testcaseId,testcase){1065 //updateExecutionTestCase({_id:execution.testcases[testcase.executionTestCaseID]._id},{$set:{"status":"Finished",result:testcase.result.result}});1066 var date = new Date();1067 var status = "Finished";1068 var qcStatus = 'Passed';1069 if((testcase.result.result != "Passed") && (testcase.result.result != "Failed")){1070 status = "Not Run";1071 }1072 1073 switch (testcase.result.result){1074 case "Passed":1075 qcStatus = 'Passed';1076 break;1077 case "Failed":1078 qcStatus = 'Failed';1079 break;1080 default:1081 qcStatus = 'N/A';1082 }1083 1084 var updateTC = function(){1085 updateExecutionTestCase({_id:testcaseId},{$set:{trace:testcase.trace,"status":status,resultID:testcase.result._id.__id,result:testcase.result.result,error:testcase.result.error,enddate:date,runtime:date-testcase.testcase.startDate,host:"",vncport:""}});1086 executionsRoute.updateExecutionTotals(executionID);1087 1088 /*unirest.post('http://localhost:8080/bumblebee/updateqc')1089 .headers({1090 'Accept-Encoding': 'gzip,deflate'1091 })1092 .query({1093 url: 'https://alm.cat.com/qcbin',1094 user: 'banovm',1095 encrypted_password: 'Xn3A404GommvK3pL7GrYoQ==',1096 domain: 'APD',1097 project: 'Minestar_QA_Copy',1098 testplandirectory: 'Subject\\Testing\\Redwood',1099 testname: testcase.testcase.dbTestCase.name,1100 mode: 'FULL',1101 testset: 'Redwood Tests',1102 testlabdirectory: 'Root\\Testing',1103 message: 'Step performed',1104 status: qcStatus,1105 overwrite_runs: 'false'1106 })1107 .end(function (response) {1108 console.log(response.body);1109 });*/1110 1111 /*common.logger.info('upload results to ALM: '+execution.uploadResultsALM);1112 common.logger.info('ALM test set path: '+execution.almTestSetPath);1113 common.logger.info('trace: '+ testcase.trace);1114 common.logger.info('status: '+ status);1115 common.logger.info('result: '+ testcase.result.result);1116 common.logger.info('error: '+ testcase.result.error);1117 common.logger.info('runtime: '+ (date-testcase.testcase.startDate));1118 common.logger.info('date: '+ date);*/1119 1120 //if execution needs to upload results to ALM1121 common.logger.info('ALMUPLOAD boolean: '+execution.uploadResultsALM);1122 common.logger.info('ALMUPLOAD almtestset: '+execution.almTestSet);1123 if(execution.uploadResultsALM){1124 almupload.uploadTestResultsToALM({testSetPath:execution.almTestSetPath,testSet:execution.almTestSet,testInstance:testcase.testcase.dbTestCase.name,status:status,1125 duration:(date-testcase.testcase.startDate),execTimeStamp:date,errorTrace:testcase.trace});1126 }1127 };1128 //update machine base state result1129 if(execution.cachedTCs){1130 if (testcase.testcase.machines.length > 0){1131 updateExecutionMachine(executionID,testcase.testcase.machines[0]._id,testcase.result.result,testcase.result._id.__id,function(){1132 updateTC();1133 });1134 }1135 else{1136 updateTC();1137 }1138 //updateExecutionMachine({testcase.testcase.machines[0]._id)},{$set:{result:testcase.result.result,resultID:testcase.result._id.__id}});1139 }1140 else{1141 updateTC();1142 }1143 var count = 0;1144 var retry = false;1145 if(testcase.result.result == "Failed"){1146 if (execution.testcases[testcase.executionTestCaseID].retryCount > 0){1147 retry = true;1148 execution.testcases[testcase.executionTestCaseID].retryCount--;1149 execution.testcases[testcase.executionTestCaseID].executing = false;1150 execution.returnVars[testcase.executionTestCaseID] = {};1151 }1152 if (execution.cachedTCs){1153 execution.baseStateFailed = true;1154 }1155 }1156 if(testcase.testcase.machines.length === 0){1157 if (retry == false){1158 //delete execution.testcases[testcase.executionTestCaseID];1159 execution.testcases[testcase.executionTestCaseID].finished = true;1160 execution.testcases[testcase.executionTestCaseID].executing = false;1161 }1162 delete execution.currentTestCases[testcase.executionTestCaseID];1163 executeTestCases(execution.testcases,executionID);1164 return;1165 }1166 testcase.testcase.machines.forEach(function(machine){1167 delete machine.runningTC;1168 count++;1169 if (count == testcase.testcase.machines.length){1170 if (retry == false){1171 //delete execution.testcases[testcase.executionTestCaseID];1172 execution.testcases[testcase.executionTestCaseID].finished = true;1173 execution.testcases[testcase.executionTestCaseID].executing = false;1174 }1175 delete execution.currentTestCases[testcase.executionTestCaseID];1176 if(execution.executingTCs != true){1177 executeTestCases(execution.testcases,executionID);1178 }1179 }1180 });1181}1182exports.formatTrace = function(trace,sourceCache,callback){formatTrace(trace,sourceCache,callback)};1183function formatTrace(trace,sourceCache,callback){1184 var newTrace = "";1185 var traceCount = 0;1186 var traces = trace.split(",");1187 traces.forEach(function(line){1188 traceCount++;1189 var fileName = line.substring(line.indexOf("(")+1,line.indexOf(":"));1190 var lineNumber = line.substring(line.indexOf(":")+1,line.indexOf(")"));1191 var location = line.substring(0,line.indexOf("("));1192 location = location.trim();1193 location = location.replace("[","");1194 var count = 0;1195 var found = false;1196 if((location.indexOf("org.codehaus.") != -1) || (location.indexOf("java.lang.") != -1) || (location.indexOf("groovy.lang.") != -1) || (location.indexOf("redwood.launcher.") != -1)|| (location.indexOf("sun.reflect.") != -1)){1197 if (line.indexOf("[") == 0){1198 newTrace += line;1199 }1200 else{1201 newTrace += ",\r\n"+line;1202 }1203 if (traceCount == traces.length){1204 callback(newTrace);1205 }1206 return;1207 }1208 if ((fileName.indexOf(".groovy") != -1) ||(fileName.indexOf(".java") != -1)){1209 sourceCache.forEach(function(file){1210 if (found == true) return;1211 if (file.indexOf("/"+fileName) != -1){1212 if(location.replace(/\./g, '/').indexOf(file.substring(0,file.lastIndexOf("/")).replace("src/", '')) != -1){1213 found = true;1214 var parsedLineNumber = (parseInt(lineNumber,10)-1).toString();1215 newTrace += ",\r\n<a style= 'color: blue;' href='javascript:openScript(""+ file +"",""+ parsedLineNumber +"")'>" + line +"</a>";1216 }1217 }1218 count++;1219 if (count == sourceCache.length){1220 if (found == false){1221 if (line.indexOf("[") == 0){1222 newTrace += line;1223 }1224 else{1225 newTrace += ",\r\n"+line;1226 }1227 }1228 if (traceCount == traces.length){1229 callback(newTrace);1230 }1231 }1232 });1233 }1234 else{1235 if (traceCount == traces.length){1236 callback(newTrace);1237 }1238 }1239 });1240}1241function markFinishedResults(results,sourceCache,callback){1242 var count = 0;1243 var result = "Passed";1244 var status = "Finished";1245 results.forEach(function(action){1246 if (action.status == "Not Run"){1247 if (action.children.length != 0){1248 markFinishedResults(action.children,sourceCache,function(childStatus,childResult,markFinished){1249 action.expanded = false;1250 if (markFinished === true){1251 action.status = "Finished";1252 action.result = "Failed";1253 action.expanded = true;1254 callback("Finished","Failed",true);1255 return;1256 }1257 count++;1258 if (childStatus == "Not Run"){1259 status = "Not Run";1260 result = "";1261 }1262 if((childStatus == "Finished") && (childResult == "Failed")){1263 result = "Failed";1264 action.expanded = true;1265 }1266 if(count == action.children.length){1267 action.result = result;1268 action.status = status;1269 if (status == "Finished"){1270 if ((action.executionflow == "Record Error Stop Test Case")&&(result == "Failed")){1271 callback(status,result,true)1272 }1273 else{1274 callback(status,result)1275 }1276 }1277 else{1278 callback(status,"")1279 }1280 }1281 })1282 }1283 else{1284 callback("Not Run","")1285 }1286 }1287 else{1288 var returnValue;1289 if ((action.executionflow == "Record Error Stop Test Case")&&(action.result == "Failed")){1290 returnValue = function(){callback("Finished","Failed",true)}1291 }1292 else{1293 returnValue = function(){callback("Finished",action.result)}1294 }1295 if(action.result == "Failed"){1296 action.expanded = true;1297 }1298 if(action.trace){1299 formatTrace(action.trace,sourceCache,function(trace){1300 if(trace != "") action.trace = trace;1301 returnValue();1302 })1303 }1304 else{1305 returnValue();1306 }1307 }1308 });1309}1310exports.agentBaseState = function(project,executionID,agentHost,port,threadID,callback){agentBaseState(project,executionID,agentHost,port,threadID,callback)};1311function agentBaseState(project,executionID,agentHost,port,threadID,callback){1312 common.logger.info("__dirname:"+path.resolve(__dirname,"../agent/executionfiles/"+executionID));1313 //copyFile(path.join(__dirname, "../public/automationscripts/"+project+"/build/jar"+projectUser+".jar"),path.join(__dirname, "../agent/executionfiles/lib"),callback());1314 //sendFileToAgent((path.join(__dirname, "../public/automationscripts/"+project+"/build/jar").toString())+projectUser+".jar","executionfiles/lib",agentHost,port,3,callback());1315 //fs.exists(path.resolve(__dirname,"../agent/executionfiles/"+executionID+"/lib"), function (exists) {1316 fs.exists(path.resolve(__dirname,"../agent/executionfiles/lib"), function (exists) {1317 if(exists == false){1318 sendAgentCommand(agentHost,port,{command:"cleanup",executionID:executionID},3,function(message){1319 if (message.error){1320 callback(message.error);1321 return;1322 }1323 //syncFilesWithAgent(agentHost,port,path.join(__dirname, '../public/automationscripts/'+project+"/bin"),"executionfiles/"+executionID+"/bin",function(error){1324 syncFilesWithAgent(agentHost,port,path.join(__dirname, '../public/automationscripts/'+project+"/bin"),"executionfiles/bin",function(error){1325 if(error) {callback(error);return}1326 //syncFilesWithAgent(agentHost,port,path.join(__dirname, '../launcher'),"executionfiles/"+executionID+"/launcher",function(){1327 syncFilesWithAgent(agentHost,port,path.join(__dirname, '../launcher'),"executionfiles/launcher",function(){1328 //syncFilesWithAgent(agentHost,port,path.join(__dirname, '../public/automationscripts/'+project+"/External Libraries"),"executionfiles/"+executionID+"/lib",function(){1329 syncFilesWithAgent(agentHost,port,path.join(__dirname, '../public/automationscripts/'+project+"/External Libraries"),"executionfiles/lib",function(){1330 //syncFilesWithAgent(agentHost,port,path.join(__dirname, '../public/automationscripts/'+project+"/build/jar_"+executionID),"executionfiles/"+executionID+"/lib",function(){1331 //syncFilesWithAgent(agentHost,port,os.tmpDir()+"/jar_"+executionID,"executionfiles/"+executionID+"/lib",function(){1332 syncFilesWithAgent(agentHost,port,os.tmpDir()+"/jar_"+executionID,"executionfiles/lib",function(){1333 syncFilesWithAgent(agentHost,port,path.join(__dirname, '../public/automationscripts/'+project+"/build/jar/projectJar"),"executionfiles/lib",function(){1334 common.logger.info("synced all files with agent");1335 sendAgentCommand(agentHost,port,{command:"start launcher",executionID:executionID,threadID:threadID},3,function(message){1336 common.logger.info("inside sendAgentCommand");1337 if ((message) && (message.error)){1338 common.logger.info("sendAgentCommand error: " & message.error)1339 callback(message.error);1340 }1341 else{1342 common.logger.info("sendAgentCommand no error")1343 callback();1344 }1345 });1346 })1347 })1348 })1349 })1350 });1351 });1352 }1353 else{1354 syncFilesWithAgent(agentHost,port,path.join(__dirname, '../public/automationscripts/'+project+"/build/jar/projectJar"),"executionfiles/lib",function(){1355 sendAgentCommand(agentHost,port,{command:"start launcher",executionID:executionID,threadID:threadID},3,function(message){1356 common.logger.info("inside sendAgentCommand");1357 if ((message) && (message.error)){1358 common.logger.info("sendAgentCommand error: " & message.error)1359 callback(message.error);1360 }1361 else{1362 common.logger.info("sendAgentCommand no error")1363 callback();1364 }1365 });1366 });1367 }1368 });1369 /*sendAgentCommand(agentHost,port,{command:"start launcher",executionID:executionID,threadID:threadID},3,function(message){1370 common.logger.info("inside sendAgentCommand");1371 if ((message) && (message.error)){1372 common.logger.info("sendAgentCommand error: " & message.error)1373 callback(message.error);1374 }1375 else{1376 common.logger.info("sendAgentCommand no error")1377 callback();1378 }1379 });*/1380}1381function syncFilesWithAgent_old(agentHost,port,rootPath,destDir,callback){1382 var walker = walk.walkSync(rootPath);1383 var fileCount = 0;1384 walker.on("file", function (root, fileStats, next) {1385 fileCount++;1386 var path = root.replace(rootPath,"");1387 var dest = "";1388 if (path == ""){1389 dest = destDir +"/"+ fileStats.name;1390 }1391 else{1392 dest = destDir + path+"/"+fileStats.name1393 }1394 sendFileToAgent(root+"/"+fileStats.name,dest,agentHost,port,3,function(){1395 fileCount--;1396 if(fileCount == 0){1397 callback();1398 }1399 });1400 });1401 walker.on("end",function(){1402 if (fileCount == 0) callback();1403 });1404}1405function syncFilesWithAgent(agentHost,port,rootPath,destDir,callback){1406 var walker = walk.walkSync(rootPath);1407 var fileCount = 0;1408 var files = [];1409 var foundError = false;1410 var sendFiles = function(){1411 if(foundError) return;1412 fileCount++;1413 if (!files[fileCount-1]){1414 callback();1415 return;1416 }1417 sendFileToAgent(files[fileCount-1].file,files[fileCount-1].dest,agentHost,port,3,function(error){1418 if(error){1419 foundError = true;1420 callback(error);1421 return;1422 }1423 if(fileCount === files.length){1424 callback();1425 }1426 else{1427 sendFiles()1428 }1429 });1430 };1431 walker.on("file", function (root, fileStats, next) {1432 var path = root.replace(rootPath,"");1433 var dest = "";1434 if (path == ""){1435 dest = destDir +"/"+ fileStats.name;1436 }1437 else{1438 dest = destDir + path+"/"+fileStats.name1439 }1440 files.push({file:root+"/"+fileStats.name,dest:dest});1441 });1442 walker.on("end",function(){1443 sendFiles()1444 });1445}1446function sendFileToAgent(file,dest,agentHost,port,retryCount,callback){1447 var stat = fs.statSync(file);1448 1449 common.logger.info("file: "+file);1450 common.logger.info("dest: "+dest);1451 var readStream = fs.createReadStream(file);1452 var boundary = '--------------------------';1453 for (var i = 0; i < 24; i++) {1454 boundary += Math.floor(Math.random() * 10).toString(16);1455 }1456 var message = '------' + boundary + '\r\n'1457 // use your file's mime type here, if known1458 + 'Content-Disposition: form-data; name="file"; filename="'+dest+'"\r\n'1459 + 'Content-Type: application/octet-stream\r\n'1460 // "name" is the name of the form field1461 // "filename" is the name of the original file1462 + 'Content-Transfer-Encoding: binary\r\n\r\n';1463 var options = {1464 hostname: agentHost,1465 port: port,1466 path: '/fileupload',1467 method: 'POST',1468 headers: {1469 //'Content-Type': 'text/plain'//,1470 'Content-Type': 'multipart/form-data; boundary=----'+boundary,1471 //'Content-Disposition': 'form-data; name="file"; filename="ProjectName.jar"',1472 //'Content-Length': 33601473 //'Content-Length': stat.size + message.length + 30 + boundary.length1474 'Content-Length': stat.size + message.length + boundary.length + 141475 }1476 };1477 var req = http.request(options, function(res) {1478 //res.setEncoding('utf8');1479 res.on('data', function (chunk) {1480 if (callback) callback();1481 });1482 });1483 req.on('error', function(e) {1484 if(retryCount <= 0){1485 if (callback) callback({error:'sendFileToAgent problem with request: ' + e.message+ ' file:'+file});1486 common.logger.error('sendFileToAgent problem with request: ' + e.message+ ' file:'+file);1487 }1488 else{1489 retryCount--;1490 setTimeout(sendFileToAgent(file,dest,agentHost,port,retryCount,callback),1000)1491 }1492 });1493 req.write(message);1494 readStream.pipe(req, { end: false });1495 readStream.on("end", function(){1496 req.end('\r\n------' + boundary + '--\r\n');1497 });1498}1499exports.sendAgentCommand = function(agentHost,port,command,retryCount,callback){sendAgentCommand(agentHost,port,command,retryCount,callback)};1500function sendAgentCommand(agentHost,port,command,retryCount,callback){1501 common.logger.info(command);1502 var options = {1503 hostname: agentHost,1504 port: port,1505 path: '/command',1506 method: 'POST',1507 headers: {1508 'Content-Type': 'application/json'1509 }1510 };1511 var req = http.request(options, function(res) {1512 res.setEncoding('utf8');1513 res.on('data', function (chunk) {1514 try{1515 var msg = JSON.parse(chunk);1516 }1517 catch(err){1518 if (callback) callback(err);1519 }1520 if((msg )&&(msg.error != null)){1521 if (callback) callback(msg.error);1522 }1523 else if (msg){1524 if(callback) callback(msg);1525 }1526 else{1527 if(callback) callback();1528 }1529 });1530 });1531 req.setTimeout(50000, function(){1532 //when timeout, this callback will be called1533 });1534 req.on('error', function(e) {1535 retryCount = 0;1536 if(retryCount <= 0){1537 if (callback) callback("Unable to connect to machine: "+agentHost + " error: " + e.message);1538 common.logger.error('sendAgentCommand problem with request: ' + e.message+ ' ');1539 }1540 else{1541 retryCount--;1542 setTimeout(sendAgentCommand(agentHost,port,command,retryCount,callback),1000)1543 }1544 });1545 // write data to request body1546 req.write(JSON.stringify(command));1547 req.end();1548}1549function resolveParamValue(value,variables){1550 var returnNULL = false;1551 if(Object.prototype.toString.call(value) == '[object Array]'){1552 if((value.length == 1) && (value[0] === "<NULL>")){1553 return [];1554 }1555 else{1556 return value;...
rununittest.js
Source:rununittest.js
...30 return;31 }32 runningTests[username] = {sourceCache:sourceCache};33 var command = {scriptLang:"Java/Groovy",username:username,command:"run action",ignoreScreenshots:true,allScreenshots:false,parameters:[],runType:"unittest",executionID:username+"unittest",script:testCaseInfo.name,type:testCaseInfo.type.toLowerCase(), threadID:99};34 execEngine.sendAgentCommand(ip,port,command,3);35 })36 })37 });38 });39 }40 })41};42exports.stopUnitTest = function(req,res){43 var ip = req.connection.remoteAddress;44 var username = req.cookies.username;45 var port = 5009;46 execEngine.sendAgentCommand(ip,port,{command:"cleanup",executionID:username+"unittest"},3);47 res.contentType('json');48 res.json({success:true});49};50exports.unitTestResult = function(req,res){51 res.contentType('json');52 res.json({success:true});53 var username = req.body.username;54 realtime.emitMessage("UnitTestStop"+req.body.username,{});55 if(req.body.trace){56 realtime.emitMessage("UnitTestRun"+username,{status:'<span style="color: red; ">Test Failed:</span>'});57 realtime.emitMessage("UnitTestRun"+username,{error:req.body.error});58 execEngine.formatTrace(req.body.trace,runningTests[username].sourceCache,function(trace){59 realtime.emitMessage("UnitTestRun"+username,{message:trace});60 });...
Using AI Code Generation
1var redwood = require('redwoodhq');2var command = "click";3var target = "id=login";4var value = "";5redwood.sendAgentCommand(command, target, value, function(err, res){6 if(err){7 console.log("error occurred");8 }9 else{10 console.log("command executed successfully");11 }12});13### redwood.sendAgentCommand(command, target, value, callback)14### redwood.sendAgentCommandAndWait(command, target, value, timeout, callback)15### redwood.sendAgentCommandAndWaitForPageToLoad(command, target, value, timeout, callback)
Using AI Code Generation
1var RedwoodClient = require("redwood-client");2var agent = {3 commands: [{4 parameters: [{5 }],6 callback: function (params, cb) {7 console.log("testCommand called with params: " + JSON.stringify(params));8 cb(null, "testCommand succeeded");9 }10 }]11};12redwoodClient.sendAgentCommand("testAgent", "testCommand", {testParam: "testParam"}, function (err, result) {13 if (err) {14 console.log("Error: " + err);15 } else {16 console.log("Result: " + result);17 }18});
Using AI Code Generation
1const redwood = require('redwoodhq');2const assert = require('assert');3const config = require('./config.json');4describe('Test Suite', function() {5 this.timeout(50000);6 before(async function() {7 await redwood.init(config);8 });9 it('Test Case', async function() {10 let response = await redwood.sendAgentCommand('test', 'test');11 assert.equal(response, 'test');12 });13});
Using AI Code Generation
1var redwood = require('redwood-client');2var client = new redwood.Client('localhost', 8000);3client.sendAgentCommand('testagent', 'test', {test: 'test'}, function(err, response) {4 console.log(err, response);5});6### sendAgentCommand(agentName, command, payload, callback)7### sendAgentCommand(agentName, command, callback)8### getAgents(callback)9### getAgent(agentName, callback)10### getAgentStatus(agentName, callback)11### getAgentStatuses(callback)12### getAgentLogs(agentName, callback)13### getAgentLogs(agentName, since, callback)14### getAgentLogs(agentName, since, until, callback)
Using AI Code Generation
1var redwood = require('redwood-client');2var client = new redwood.Client();3client.sendAgentCommand('myagent', 'mycommand', 'mydata', function(err, result) {4 if (err) {5 console.log('Error: ' + err);6 } else {7 console.log('Result: ' + result);8 }9});10var redwood = require('redwood-client');11var client = new redwood.Client();12client.sendAgentCommand('myagent', 'mycommand', 'mydata', function(err, result) {13 if (err) {14 console.log('Error: ' + err);15 } else {16 console.log('Result: ' + result);17 }18});19var redwood = require('redwood-client');20var client = new redwood.Client();21client.sendAgentCommand('myagent', 'mycommand', 'mydata', function(err, result) {22 if (err) {23 console.log('Error: ' + err);24 } else {25 console.log('Result: ' + result);26 }27});28var redwood = require('redwood-client');29var client = new redwood.Client();30client.sendAgentCommand('myagent', 'mycommand', 'mydata', function(err, result) {31 if (err) {32 console.log('Error: ' + err);33 } else {34 console.log('Result: ' + result);35 }36});37var redwood = require('redwood-client');38var client = new redwood.Client();39client.sendAgentCommand('myagent', 'mycommand', 'mydata', function(err, result) {40 if (err) {41 console.log('Error: ' + err);42 } else {43 console.log('Result: ' + result);44 }45});
Using AI Code Generation
1var redwood = require('redwood');2var agent = redwood.agent;3var agentId = 'agentId';4var command = 'status';5var commandArgs = '';6agent.sendAgentCommand(agentId, command, commandArgs, function(err, result) {7 if (err) {8 console.log('Error sending agent command: ' + err);9 } else {10 console.log(result);11 }12});
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.
You could also refer to video tutorials over LambdaTest YouTube channel to get step by step demonstration from industry experts.
Get 100 minutes of automation test minutes FREE!!