Apologies if this has been answered before, I spent most of today looking and found some similar issues but nothing that answered my specific problem.
I am posting to a TransactionAPI with 'TransactionID'-> sleeping thread for 10 minutes (because this is ensures that the transaction posts in the next step) -> calling read api with
Then match response.results[*].trans.id contains TransactionID
this currently works, but sleep isn't great.. and I wanted to take full advantage of karate.
The [*] is because the new TransactionID appears in the final index of the returned array response.
so the first time it calls the readAPI it gets an array of [5], and the new TransactionID will appear in [6] (and I couldn't figure out how to make it get array.length + 1 and wait for that one to appear)
Reading the responses here Karate framework retry until not working as expected and the linked ones inside i tried a few things:
And retry until response.results[-1].trans.id.includes('TransactionID')
And retry until response.results[(#.length-1)].trans.id.includes('TransactionID')
These return an error:
org.graalvm.polyglot.PolyglotException: SyntaxError: Unnamed:1:18 Expected an operand but found error
I tried the in-line javascript function mentioned in the above link, but could not get it to work either.
Javascript function mentioned:
* def isValid = function(x){ return karate.match(x, { tokens: '##[_ > 0]' }).pass }
# ...
And retry until isValid(response)
So indexing to -1 will not work because that is JsonPath and not JavaScript.
Try this:
# set this by doing a call before if needed
* def prevLength = response.length
* def isValid = function(x){ return x.length > prevLength }
# ...
* retry until isValid(response)
My guess is that it is more than enough to achieve what you want.
Related
I have this algorithm exercise that is very popular with developers that returns:
steps(3)
#
##
###
steps(5)
#
##
###
####
#####
I am studying a version of it developed in a recursive way. The code below is working fine.
function steps(n, row = 0 , stair = '') {
if(n === row) {
return;
}
if(n === stair.length) {
console.log(stair)
return steps(n, row + 1)
}
if (stair.length <= row) {
stair += '#';
} else {
stair += ' '
}
steps(n, row, stair)
}
steps(3)
My only doubt is related to the importance of the 'return' in this part of the code:
if(n === stair.length) {
console.log(stair)
return steps(n, row + 1) // <--- this 'return'
}
If I delete the 'return', like this way:
if(n === stair.length) {
console.log(stair)
steps(n, row + 1) // <-- without the return
}
this generates a looping error on console:
Maximum call stack size exceeded
I want to understand why this happens under the hood. I still don't have much practice with recursive functions.
if n===stair.length, you don't want to make the call steps(n, row, stair) at the bottom of the function, which you would if you left out the return.
There are kind of 2 ways to think about recursive functions. The first is to actually look at what literally happens -- that is, look at an example and "unroll" by noting all of the calls to the function steps. This is safe to think about and is easy.
The second way is more "magical. In this way of thinking, you do NOT consider a "big picture" or think about multiple calls of the recursive function. Instead, you form a coherent idea of what your recursive function SHOULD accept as arguments and what it SHOULD return. Then, you can always write the body of your recursive function by using that function in the way you assume it should work. This can be more confusing to grasp, but once you "get" it, it's very elegant and is the more useful mode of thinking.
Let's use the first mode of thinking here, since it's probably easier.
Can you tell me how many times steps gets called and with which arguments, in order? For example, the first call is steps(5, 0, ''). Then, what is the second call of steps that will happen? Follow these steps (heh) and you should see what the issue is.
It breaks because your code terminates when row === n. That line is the only place where row is changed. Without it, the code will produce output like this:
#
#
#
#
#
...
Since you're handling this in a recursive function, javascript runs out of stack frames before it gets infinitely deep.
I'm new to lexing and parsing so sorry if the title isn't clear enough.
Basically, I'm using Jison to parse some text and I am trying to get the lexer to comprehend indentation. Here's the bit in question:
(\r\n|\r|\n)+\s* %{
parser.indentCount = parser.indentCount || [0];
var indentation = yytext.replace(/^(\r\n|\r|\n)+/, '').length;
if (indentation > parser.indentCount[0]) {
parser.indentCount.unshift(indentation);
return 'INDENT';
}
var tokens = [];
while (indentation < parser.indentCount[0]) {
tokens.push('DEDENT');
parser.indentCount.shift();
}
if (tokens.length) {
return tokens;
}
if (!indentation.length) {
return 'NEWLINE';
}
%}
So far, almost all of that works as expected. The one problem is the line where I attempt to return an array of DEDENT tokens. It appears that Jison is just converting that array into a string which causes me to get a parse error like Expecting ........, got DEDENT,DEDENT.
What I'm hoping I can do to get around this is manually push some DEDENT tokens onto the stack. Maybe with a function like this.pushToken('DEDENT') or something along those lines. But the Jison documentation is not so great and I could use some help.
Any thoughts?
EDIT:
I seem to have been able to hack my way around this after looking at the generated parser code. Here's what seems to work...
if (tokens.length) {
var args = arguments;
tokens.slice(1).forEach(function () {
lexer.performAction.apply(this, args);
}.bind(this));
return 'DEDENT';
}
This tricks the lexer into performing another action using the exact same input for each DEDENT we have in the stack, thus allowing it to add in the proper dedents. However, it feels gross and I'm worried there could be unforeseen problems.
I would still love it if anyone had any ideas on a better way to do this.
After a couple of days I ended up figuring out a better answer. Here's what it looks like:
(\r\n|\r|\n)+[ \t]* %{
parser.indentCount = parser.indentCount || [0];
parser.forceDedent = parser.forceDedent || 0;
if (parser.forceDedent) {
parser.forceDedent -= 1;
this.unput(yytext);
return 'DEDENT';
}
var indentation = yytext.replace(/^(\r\n|\r|\n)+/, '').length;
if (indentation > parser.indentCount[0]) {
parser.indentCount.unshift(indentation);
return 'INDENT';
}
var dedents = [];
while (indentation < parser.indentCount[0]) {
dedents.push('DEDENT');
parser.indentCount.shift();
}
if (dedents.length) {
parser.forceDedent = dedents.length - 1;
this.unput(yytext);
return 'DEDENT';
}
return `NEWLINE`;
%}
Firstly, I modified my capture regex to make sure I wasn't inadvertently capturing extra newlines after a series of non-newline spaces.
Next, we make sure there are 2 "global" variables. indentCount will track our current indentation length. forceDedent will force us to return a DEDENT if it has a value above 0.
Next, we have a condition to test for a truthy value on forceDedent. If we have one, we'll decrement it by 1 and use the unput function to make sure we iterate on this same pattern at least one more time, but for this iteration, we'll return a DEDENT.
If we haven't returned, we get the length of our current indentation.
If the current indentation is greater than our most recent indentation, we'll track that on our indentCount variable and return an INDENT.
If we haven't returned, it's time to prepare to possible dedents. We'll make an array to track them.
When we detect a dedent, the user could be attempting to close 1 or more blocks all at once. So we need to include a DEDENT for as many blocks as the user is closing. We set up a loop and say that for as long as the current indentation is less than our most recent indentation, we'll add a DEDENT to our list and shift an item off of our indentCount.
If we tracked any dedents, we need to make sure all of them get returned by the lexer. Because the lexer can only return 1 token at a time, we'll return 1 here, but we'll also set our forceDedent variable to make sure we return the rest of them as well. To make sure we iterate on this pattern again and those dedents can be inserted, we'll use the unput function.
In any other case, we'll just return a NEWLINE.
This is more of an elementry SoapUI Groovy Scdript Question.
In a Response that returns 100.000
I'm to assert that my return value is < the Response
If I do:
max = 100
resonse = ('${responseTC#xyz..."')
assert resposne < max
"Error is (java.lang.Integer cannot be cast to java.lang.String"
I have found some ways around this but I want to ask you experts - the "expert" way of handling this.
Thank you,
Rob
the most natural and "expert" way is:
int max = 100
def response = responseString.toFloat()
assert max > response
Also in soapUI I now used toDouble() or toBigDecimal() at the end of the context.expand. I did not have to use "int" for any hard coded value. I'm still learning but it seems when you get responses w/ decimal values - asserting is annoying. Sometimes I need to round() the #.
I created this tester script assertion (all the toFloat(), as Int, even applying no method to the def context Failed on me). Even if they passed an == assertion, I couldn't do MATH on them sub/add etc.
So far I see the safe way is toBigDecimal() & toDouble().
/* Look at the end of each 'def'----notice the method
* Each def line is the same exact response value
* the ending method will re-translate how the computer/ SoapUI looks at this numerical value. If using this code - replace my def context.expand w/ one of your own.
*/
def householdMAGI_toBigDec = context.expand( '${Addition_Subtraction2#Response#declare namespace ns2=\'http://something.com/\'; //ns2:QhpDResponse[1]/QhpDResponse[1]/TaxHouseholdEligibility[1]/HouseholdMagi[1]}' ).toBigDecimal()
log.info ("toBigDecimal: "+householdMAGI_toBigDec) // '45210.56'
def householdMAGI_toDouble = context.expand( '${Addition_Subtraction2#Response#declare namespace ns2=\'http://something.com/\'; //ns2:QhpDResponse[1]/QhpDResponse[1]/TaxHouseholdEligibility[1]/HouseholdMagi[1]}' ).toDouble()
log.info ("toDouble: "+householdMAGI_toDouble) // '45210.56''
/*Here we are going to define the same number ourselves manually in various ways
* Below under each def - one at at time remove the // from an assertiong and run the script
* The results are already noted after each assertion
*/
def magi_a = 45210.56
assert householdMAGI_toBigDec == magi_a //---PASSES (When set toBigDecimal()
assert householdMAGI_toDouble == magi_a //---PASSES (When set toDouble()
calc_magi_a1 = magi_a + householdMAGI_toBigDec
log.info ("calc_magi_a1: "+calc_magi_a1) //---Successful Addition
calc_magi_a2 = magi_a + householdMAGI_toDouble
log.info ("calc_magi_a2: "+calc_magi_a2) //---Successful Addition
I have a simple project that does some generic array calculations and returns the result in a grid. I needed a short way to scan an array for the maximum value and tried using this:
var max = Math.max.bind( Math.max );
var vector_max = Function.apply.bind( max, null );
Now, this works great when I am not debugging. But, if I wrap a test function around any statement, like, say:
function tester() {
var r = 0;
return r;
}
..., set a breakpoint anywhere in this function, and click debug, I get an error:
"Typeerror: This operation is not allowed. (line XXX, file xxx)"
This happens even in a completely new script attached to an empty sheet. Of course, Google has no documentation on their script debugger and no references to any limitations, so, I am totally in the dark.
Any ideas?
I can also reproduce this. It indeed seems like a bug in the debugger! :)
You should report this in the Apps Script issue tracker. And in the mean time use another implementation for your vector_max function to debug your code. For example:
function vector_max(a){ return a.reduce(function(r,v){ return r < v ? v : r; }, -Infinity); }
I have a requirement that the user can provide arbitrary statements which can be stored in a function and called later to get a return value. A simple example of this is that userInput might be
var x = 10;
x;
I would store this via
var callback = function() {
return eval(userInput);
}
and then running callback() returns 10 as expected.
However, I also need to support the case with an explicit return statement, ie userInput might be
var x = 10;
return x;
In this case the eval method above will fail with SyntaxError: return not in function. Instead I could store callback as
var callback = new Function(userInput);
My issue is that I would like to combine these two approaches according the rule 'get explicit return value otherwise get the result of the last executed statement'. In particular this can't be done with analysis of the code at callback creation time as the user could potentially do something odd like
if(envVar < 10)
return a;
b * 0.5;
which combines both.
Any thoughts on how to structure the creation of the callback function to accommodate these possible inputs? Unfortunately it is not possible to enforce one style or the other on the user.
UPDATE to answer some of the comments below.
One solution suggested is to search for a return token and choose between new Function and eval. This doesn't work for my last example, see http://jsfiddle.net/ZGb6z/2/ - out4 should be "no" but ends up being undefined as the last executed statement is not returned.
Another suggestion is to modify the user input to add an explicit return on the last line if one is not found. Unfortunately it's not possible to know which statement will be executed last. Consider
var x = 10;
switch(x) {
case 10:
100;
break;
default:
200;
break;
}
When called it should return 100, but it would take some serious analysis to determine where to put returns for arbitrary code.
Just use a try catch, manipulating the input will be very painful for you, and try catch can't really make your code any more obtuse at this point.
var failback = function () {
try {
return eval(userInput);
} catch (e) {
return Function(userInput);
}
};
What I would really suggest is investing in a parser, kind of like how Angular does it. That kind of thing would prevent your users from doing whatever the hell they want, introducing attack vectors, yadda, yadda, yadda.
Either manage your expectations or manage your user's expectations. eval and new Function() are not suitable for your requirements if you require mixed usage of explicit and non-explicit return statements in the same user-input. You will continue to find issues following either of these routes.
Simply searching for the word return is not sufficient either... var returning = true; or var a = 'return'; or /* return true */ true; will all throw false positives.
Managing your expectations: To do such a thing you require a form of lexer and parser, at which point you can do away with eval entirely and execute your own safe functions based on the parsed input. This is the best approach when execution of user input has to occur anyway as you can ensure that nothing gets executed you do not wish to permit. If you want to cover these sort of edge cases and permit strange user input then you must be prepared to increase the size and development time of your application. I have built a few applications executing user generated code and have always come to the conclusion this is the correct route to go down.
Managing your user's expectations: Provide a guide, tell them not to mix explicit returns with non-explicit returns, these are strange coding practices anyway. Better yet explicitly tell them to include or omit the return statement. There is no shame in asking your users to follow them, especially if it allows you to improve their experience elsewhere.
There I was thinking I'd only see problems like this at the code golf stack exchange :)
My solution is here: http://jsfiddle.net/hKq87/1
It essentially replaces the 'return' statement with an exception that has a special string prefixed to it. If we see that string, we know we are actually returning a value, and return it rather than re-raising the exception.
The reason I chose to throw an exception rather than replace the return statement with a function call was because it is hard to know where the JS code evaluated for the return really ends. It could be split across multiple lines, contain several special characters and may not even have the optional semi-colon at the end. So I concatenate a string to whatever the value being returned is and throw it, as the throw keyword doesn't require it's argument to be wrapped in parentheses.
In addition, throwing exceptions provides me a convenient way to immediately terminate execution of the code block, without halting other JS execution.
Here is the callback method:
var callback = function(userInput) {
var returned = undefined;
userInput = userInput.replace(/(^|[\(\\)[\]{};,\s])return(\s*[^\s;])?/gi, function(m, b, e){
return b + " throw '__RETURNED_VALUE'" +
(e !== undefined ? "+" + e : "");
});
try {
returned = eval(userInput);
} catch (e) {
if (e.indexOf("__RETURNED_VALUE") == 0) {
returned = e.substring("__RETURNED_VALUE".length) || undefined;
}
else {
throw e;
}
}
return returned;
}
The regex above accounts for variables that may end with the string "return", that we would not want to replace as it is not a return statement. It also allows for return statements within braces, without trailing semi-colons or at the very beginning/end.
One issue with the current method is that you can not use the (rare) comma operator in a return statement, or expect numerical values to be returned correctly. The last test case in the jsfiddle demonstrates this. An example from here:
//original
return 5 * 2 + 3, 22;
//modified
throw '__RETURNED_VALUE='+ 5 * 2 + 3, 22;
//apply * operator
throw '__RETURNED_VALUE='+ 10 + 3, 22;
//apply + operators
throw '__RETURNED_VALUE=103', 22;
//apply , operator
throw 22;
This problem can be avoided by completely eliminating the prefix '__RETURNED_VALUE=' and just replacing 'return' with 'throw'. However, this means that the code provided must run without throwing exceptions, which I thought to be a harder constraint than just crafting return statements to be simple (avoiding comma operators, non-parenthesized arithmetic, etc.). In addition, if a user ever creates a return statement that we can't handle with the current code, we conveniently throw an exception for it so it easily comes to our attention.
jsFiddle Demo
Lets assume your user can be a little smarter than the average bear. We are going to ask them to specifically provide an initial value and then a callback with an expression for that value.
The main benefit of doing this is that you avoid eval, and actually have a nice implementation that is re-usable as opposed to being subject to later refactoring.
This way also provides a separation of where the input comes from and where the examination comes from. Although the provided example only shows integer input, really it could be another call with absolutely no knowledge of the value aside that it needs to conform to the callback logic.
function expression(x,callback){
return callback(x);
}
out1.innerHTML = expression(8,function(x){
return x;
});
out2.innerHTML = expression(10,function(x){
return x;
});
out3.innerHTML = expression(10,function(x){
if(x === 10) return "yes"; "no";
});
out4.innerHTML = expression(8,function(x){
return x === 10 ? "yes" : "no";
});