What's the best method to catenate together multiple input parameters in Robot Framework? - url

I am trying to minimize my Robot Keywords and in my URL testing I sometimes have to build up a URL from a group of inputs, that can vary depending on the test. The length can be anywhere from 4 to 7 input parameters that I am catenating to pass back one URL with whatever input parameters are passed in.
If I have a keyword that does the following:
inputs: ${location01} ${location02} ${location03}=${EMPTY} ${location04}=${EMPTY}
${my_url} = Catenate SEPARATOR=/ ${location01} ${location02} ${location03} ${location04}
[Return] ${my_url}
What is the best method to test if ${location03} is empty, and I can therefore skip the rest?
When I have tried to test for ${EMPTY}, so that the following will be false
${my_url} Run Keyword IF '${location03}'!='${EMPTY} Catenate SEPARATOR=/ ${location01} ${location02} ${location03} ${location04}
I still get a catenated string but end up with extra /'s at the end, so ${my_url} looks like:
${my_url} = ${location01}/${location02}//
When I want:
${my_url} = ${location01}/${location02}
I may be missing how Robot is doing checks, and initializing my variables, I'm sure there is a way to do this that is eluding me at the moment.

Sounds like you need to use #{args} to handle variable number of parameters:
*** Keywords ***
Create URL
[Arguments] #{args}
${url}= Catenate SEPARATOR=/ #{args}
*** Test Cases ***
Test Url
Create URL http://stackoverflow.com questions robotframework
Create URL http://stackoverflow.com questions

Related

How to set io.output() back to default output file?

I am learning how work with files in Lua, and I came across a problem.
I know that:
io.output() allows me to specify the file that I will write output to.
The io.write() function simply gets a number of string arguments and writes them to the current output file.
io.close() then closes the file I am reading or writing on.
I first set io.output() to "myNewFile.txt" then I did io.write("Hello World!").
io.output("myNewFile.txt")
io.write("Hello World!")
This part worked well and myNewFile.txt got Hello World written to it.
Then I wrote io.close() to close the myNewFile.txt.
After that, I wrote io.write("Hello World!"), but I got an error:
C:\\Program Files\\lua\\lua54.exe: ...OneDrive\\Documents\\learning lua\\steve's teacher\\main.lua:9: default output file is closed stack traceback: \[C\]: in function 'io.write' ...OneDrive\\Documents\\learning lua\\steve's teacher\\main.lua:9: in main chunk \[C\]: in ?
I wanted io.write("Hello World!") to write Hello World in the terminal. I know can use print() but print() function adds extra characters like \n and things like that.
So my question is, how do I write Hello World in the terminal using io.write("Hello World!") in this situation?
I tried to search this error up on Google, but there weren't any results. I also tried joining many Discord servers, but I didn't get a proper response. I am a new developer to Lua so this all is really confusing to me.
After io.close() do a io.output(io.stdout) to set it back.
The clean way
local oldout = io.output() -- without argument returns actual output
io.output("file") -- set to a filename
-- do file operations here
-- use io.flush() where it is necessary
io.close() -- close file also do a flush()
io.output(oldout) -- set back to oldout ( normally io.stdout )
-- changing io.output() back should also close() and flush() the "file"
-- But better doublecheck this when using userdata without experience

Validate URL in Informix 4GL program

In my Informix 4GL program, I have an input field where the user can insert a URL and the feed is later being sent over to the web via a script.
How can I validate the URL at the time of input, to ensure that it's a live link? Can I make a call and see if I get back any errors?
I4GL checking the URL
There is no built-in function to do that (URLs didn't exist when I4GL was invented, amongst other things).
If you can devise a C method to do that, you can arrange to call that method through the C interface. You'll write the method in native C, and then write an I4GL-callable C interface function using the normal rules. When you build the program with I4GL c-code, you'll link the extra C functions too. If you build the program with I4GL-RDS (p-code), you'll need to build a custom runner with the extra function(s) exposed. All of this is standard technique for I4GL.
In general terms, the C interface code you'll need will look vaguely like this:
#include <fglsys.h>
// Standard interface for I4GL-callable C functions
extern int i4gl_validate_url(int nargs);
// Using obsolescent interface functions
int i4gl_validate_url(int nargs)
{
if (nargs != 1)
fgl_fatal(__FILE__, __LINE__, -1318);
char url[4096];
popstring(url, sizeof(url));
int r = validate_url(url); // Your C function
retint(r);
return 1;
}
You can and should check the manuals but that code, using the 'old style' function names, should compile correctly. The code can be called in I4GL like this:
DEFINE url CHAR(256)
DEFINE rc INTEGER
LET url = "http://www.google.com/"
LET rc = i4gl_validate_url(url)
IF rc != 0 THEN
ERROR "Invalid URL"
ELSE
MESSAGE "URL is OK"
END IF
Or along those general lines. Exactly what values you return depends on your decisions about how to return a status from validate_url(). If need so be, you can return multiple values from the interface function (e.g. error number and text of error message). Etc. This is about the simplest possible design for calling some C code to validate a URL from within an I4GL program.
Modern C interface functions
The function names in the interface library were all changed in the mid-00's, though the old names still exist as macros. The old names were:
popstring(char *buffer, int buflen)
retint(int retval)
fgl_fatal(const char *file, int line, int errnum)
You can find the revised documentation at IBM Informix 4GL v7.50.xC3: Publication library in PDF in the 4GL Reference Manual, and you need Appendix C "Using C with IBM Informix 4GL".
The new names start ibm_lib4gl_:
ibm_libi4gl_popMInt()
ibm_libi4gl_popString()
As to the error reporting function, there is one — it exists — but I don't have access to documentation for it any more. It'll be in the fglsys.h header. It takes an error number as one argument; there's the file name and a line number as the other arguments. And it will, presumably, be ibm_lib4gl_… and there'll be probably be Fatal or perhaps fatal (or maybe Err or err) in the rest of the name.
I4GL running a script that checks the URL
Wouldn't it be easier to write a shell script to get the status code? That might work if I can return the status code or any existing results back to the program into a variable? Can I do that?
Quite possibly. If you want the contents of the URL as a string, though, you'll might end up wanting to call C. It is certainly worth thinking about whether calling a shell script from within I4GL is doable. If so, it will be a lot simpler (RUN "script", IIRC, where the literal string would probably be replaced by a built-up string containing the command and the URL). I believe there are file I/O functions in I4GL now, too, so if you can get the script to write a file (trivial), you can read the data from the file without needing custom C. For a long time, you needed custom C to do that.
I just need to validate the URL before storing it into the database. I was thinking about:
#!/bin/bash
read -p "URL to check: " url
if curl --output /dev/null --silent --head --fail "$url"; then
printf '%s\n' "$url exist"
else
printf '%s\n' "$url does not exist"
fi
but I just need the output instead of /dev/null to be into a variable. I believe the only option is to dump the output into a temp file and read from there.
Instead of having I4GL run the code to validate the URL, have I4GL run a script to validate the URL. Use the exit status of the script and dump the output of curl into /dev/null.
FUNCTION check_url(url)
DEFINE url VARCHAR(255)
DEFINE command_line VARCHAR(255)
DEFINE exit_status INTEGER
LET command_line = "check_url ", url
RUN command_line RETURNING exit_status
RETURN exit_status
END FUNCTION {check_url}
Your calling code can analyze exit_status to see whether it worked. A value of 0 indicates success; non-zero indicates a problem of some sort, which can be deemed 'URL does not work'.
Make sure the check_url script (a) exits with status zero on success and non-zero on any sort of failure, and (b) doesn't write anything to standard output (or standard error) by default. The writing to standard error or output will screw up screen layouts, etc, and you do not want that. (You can obviously have options to the script that enable standard output, or you can invoke the script with options to suppress standard output and standard error, or redirect the outputs to /dev/null; however, when used by the I4GL program, it should be silent.)
Your 'script' (check_url) could be as simple as:
#!/bin/bash
exec curl --output /dev/null --silent --head --fail "${1:-http://www.example.com/"
This passes the first argument to curl, or the non-existent example.com URL if no argument is given, and replaces itself with curl, which generates a zero/non-zero exit status as required. You might add 2>/dev/null to the end of the command line to ensure that error messages are not seen. (Note that it will be hell debugging this if anything goes wrong; make sure you've got provision for debugging.)
The exec is a minor optimization; you could omit it with almost no difference in result. (I could devise a scheme that would probably spot the difference; it involves signalling the curl process, though — kill -9 9999 or similar, where the 9999 is the PID of the curl process — and isn't of practical significance.)
Given that the script is just one line of code that invokes another program, it would be possible to embed all that in the I4GL program. However, having an external shell script (or Perl script, or …) has merits of flexibility; you can edit it to log attempts, for example, without changing the I4GL code at all. One more file to distribute, but better flexibility — keep a separate script, even though it could all be embedded in the I4GL.
As Jonathan said "URLs didn't exist when I4GL was invented, amongst other things". What you will find is that the products that have grown to superceed Informix-4gl such as FourJs Genero will cater for new technologies and other things invented after I4GL.
Using FourJs Genero, the code below will do what you are after using the Informix 4gl syntax you are familiar with
IMPORT com
MAIN
-- Should succeed and display 1
DISPLAY validate_url("http://www.google.com")
DISPLAY validate_url("http://www.4js.com/online_documentation/fjs-fgl-manual-html/index.html#c_fgl_nf.html") -- link to some of the features added to I4GL by Genero
-- Should fail and display 0
DISPLAY validate_url("http://www.google.com/testing")
DISPLAY validate_url("http://www.google2.com")
END MAIN
FUNCTION validate_url(url)
DEFINE url STRING
DEFINE req com.HttpRequest
DEFINE resp com.HttpResponse
-- Returns TRUE if http request to a URL returns 200
TRY
LET req = com.HttpRequest.create(url)
CALL req.doRequest()
LET resp = req.getResponse()
IF resp.getStatusCode() = 200 THEN
RETURN TRUE
END IF
-- May want to handle other HTTP status codes
CATCH
-- May want to capture case if not connected to internet etc
END TRY
RETURN FALSE
END FUNCTION

override assert in lua

my setup board uses lighttpd to provide web UI to the board.
It uses lua and JS to draw logic.
What I am seeing is If I enter an URL as "IPofboard/somejunkhere"; its properly throwing "404 not found"
But when I fire "IPofboard/somejunk.lp" (which is some junk lua file); It produces an "assert" error for file not found. Thats how lua works.
But I want to modify/override this assert to show same custom message as "404 not found"
any idea?
I am new to lua. Is it even doable?
As lhf mentions, it is very easy to redefine any function in Lua, but I think this may not be what you need. The issue is that after you do
local origAssert = assert
assert = function(message)
do something (possibly using origAssert)
end
then every function call that uses assert will use your new assert function, which is probably not what you want. Instead, you can call your function in "protected" mode: this will trap the assertion as an error message, and you can then decide what to do. For example,
ok, ret1, ret2 = pcall(yourFunction, arg1)
if not ok then
do something, possibly print ret1 (the error message)
end
Same thing if you are requiring a module that does some initialization:
ok, module = pcall(require, yourModuleName)
if not ok then
print("ERROR:", module) -- if not ok then module is err message
end
I'm not familiar with how lighttpd embeds Lua, but in Lua you can redefine anything, including functions from the standard Lua library, such as assert.

get value of export_includes for target

I have a target in waf defined like this:
bld(...,
target='asdf',
export_includes='.'
)
I want to get the value of the export_includes for that target (for use in some custom commands).
How do I get it?
Use a custom rule with the features for whatever target you're processing. Ex, let's say I'm processing C:
def print_includes(t):
print(t.env.INCPATHS)
bld(features='c', use='asdf', rule=print_includes)
The task t's env will contain all relevant environment variables as derived from the bld.env, but with all the additional flags stemming from use-ing the target.
i.e. if I originally had bld.env.INCPATHS == ['old-path' 'other-old-path'], it'll end up being printed out as ['old-path', 'other-old-path', 'export_include_for_asdf_here'].

URLTrigger plugin. Need examples for TXT-RegEx or XML-XPath

So, I try to use plugin https://wiki.jenkins-ci.org/display/JENKINS/URLTrigger+Plugin.
I want to trigger my Jenkins job when the text "Last build (#40), 17 hr ago" in the response of provided URL is changed (build number will be different after each build).
So I made following configurations:
1. Build trigger: Set [URLTrigger] - Poll with a URL.
2. Specified URL to another Jenkins: http://mydomain:8080/job/MasterJobDoNothing/
3. Set Inspect URL content option
4. Set Monitor the contents of a TEXT response
5. Set following regular expression: ^Last build[.]*
6. Set Schedule every minute: * * * * *
7. Trigger the job on another Jenkins
Actual result: My job wasn't triggered.
Then I tried to deal with XML/XPath and specify
8. Set Monitor the contents of an XML response
9. Set XPath: //*[#id="side-panel"] (also tried with one "/")
Actual result: the same.
Tell me please what I'm doing wrong? Please provide examples of RegEx or XPath if possible.
Thanks, Dima
I managed to trigger reliably with regex setting.
The regex pattern matches each line of the input.
No need to use ^ or $. it always match line start to line end.
This plugin compares the contents of the matched lines. It triggers if different.
This plugin compares the count of the matched lines. It triggers if the count is different.
This plugin uses matches() method of java.util.regex.Matcher. So the regex pattern should conform to it. (it's fairly normal regex)
As for your example,
Last build.*
may work.
Refs:
Reference of regex patten:
http://docs.oracle.com/javase/7/docs/api/java/util/regex/Pattern.html
Reference of Matcher: http://docs.oracle.com/javase/7/docs/api/java/util/regex/Matcher.html#matches()
The regex trigger source code:
github.com/jenkinsci/urltrigger-plugin/blame/master/src/main/java/org/jenkinsci/plugins/urltrigger/content/TEXTContentType.java
I'd recommend to use the "RSS for all" link as a trigger URL instead, and /feed/entry[1] as the XPath expression for the XML response content nature.
PS: I was using PathEnq to debug the XPath expression.

Resources