How to define a global token in Lexer.g4? - antlr4

i'm using Antlr4 and trying to add a global token in lexer.g4 so i can use it inside any mode
//Lexer.g4
TEST: 'test'->pushMode(testMode);
mode testMode;
PRE: 'pre';
POST: 'post'->popMode;
//Parser.g4
testStatement: TEST PRE TEST POST;
i can't use TEST inside the testMode because it has been defined outside the mode.
any solution to define this token so it can be global and i can use it inside any mode ?!

Use the type command to set the token type:
TEST: 'test'-> pushMode(testMode);
mode testMode;
TEST_X: 'test'-> type(TEST);
....

Related

Best practices for managing multiple environment variables in prodution

Although I am not familiar with DevOps best practices, I am trying to come up with a reliable and efficient method for managing multiple variables in production. The following represents my current approach:
/
|ENV_VAR.sh
|--/api1
|--/staging.api1
|--/api2
|--/staging.api2
Where:
ENV_VAR.sh
### API 1 variables ###
export API1_VAR_1=foo
export API1_VAR_2=foo2
export API1_STAG_VAR_1=foo_stag
export API1_VAR_2=foo2_stag2
### API 2 variables ###
export API2_VAR_1=foo
export API2_VAR_2=foo2
export API2_STAG_VAR_1=foo_stag
export API2_VAR_2=foo2_stag2
The API 1 and 2 are two nodejs-based apps running in the same server using a reverse-proxy configuration.
If nothing goes bad with the server (e.g. unexpected shutdown), I just have to (re)set the variables once in a while via SOURCE ENV_VAR.SH in order to make sure that new variables are defined.
Before proceeding with this approach, I would like to know whether it is correct at all, or if it has a big flaw.
If this approach is alright, how to automatically (re)source the environment variables from the package.json whenever a new version of any App is deployed? (just to guarantee that the variables are still defined)
Thanks in advance.
I like using Loren West's config package for these configuration parameters. I happen to like to extend it with the properties package: that way I don't have to put parameters in valid, comment-free, JSON format. JSON5 also helps solve the readability problem, but I haven't tried it.
Why do I like this?
It gives a structured way of dealing with development / test / staging / production environments. It keys off the ENV environment variable, which of course has values like development and production.
All properties files go into a single directory, typically ./config. Your production krewe can tell what they're looking at. default.properties, development.properties and production.properties are the names of typical files.
Most configuration parameters don't have to be secret, and therefore they can be committed to your repository.
Secrets (passwords, connection strings, API keys, etc) can be stored in local.properties files placed into ./config by your deployment system. (Mention local.properties in your .gitignore file.)
Secrets can also be loaded from environment variables, named in a file called ./config/custom_environment_variables.json.
It works nicely with pm2.
This is really easy to configure.
Your files:
default.properties (used when not overridden by another file)
[API1]
VAR_1 = foo
VAR_2 = foo2
[API2]
VAR_1 = foo
VAR_2 = foo_for_api2
staging.properties
[API1]
VAR_1 = foo_stag
VAR_2 = foo2_stag2
[API2]
VAR_1=foo_stag
VAR_2=foo2_stag2
custom_environment_variables.json
{
"API1" : {
"password": "API1_PASS"
},
"API2" : {
"password": "API2_PASS"
}
}
Your nodejs program:
const config = require( 'config' )
require( 'properties' )
const appConfig = config.get( 'API1' )
const var1 = appConfig.VAR_1
const password = appConfig.password
Then you run your program with API1_PASS=yaddablah nodejs program.js and you get all your configs.

Global Variables - Katalon Studio

I am working with Cucumber & Groovy in Katalon Studio.
I have ten feature file lines in Cucumber and corresponding step definitions.
In my cucumber feature file first step has the indicator where if the first line is passed with the parameter with "NO RUN", the test case should not run and it should be moved to the next test case.
So, I thought, I will use the Global variable indicator where I can handle in the test and assign the values. I see that and could create the Global Variable (RUN INDICATOR) under the Execution profile. But, not sure how I need to use that variable in the test script or refer.
Can someone please provide the inputs on this to proceed further ?
Step Definition
#Given("running indicator flag (.*)")
def run_indicator_flag(String ind1) {
println "Passing Indicator " + ind1
assert ((ind1!='') || (ind1!='N'))
WebUI.openBrowser('', FailureHandling.STOP_ON_FAILURE)
}
You can use test listeners to do that.
Create a Global Variable with the empty string value (You need to do this before actually running the test case/suite):
GlobalVariable.RUN_INDICATOR = ''
You will update its value either manually or preceding test will update it to whatever value you wish.
Create a test listener with the following code
#BeforeTestCase
def sampleBeforeTestCase(TestCaseContext testCaseContext) {
if(GlobalVariable.RUN_INDICATOR=='NO RUN'){
testCaseContext.skipThisTestCase()
println "Test Case skipped"
}
}
If the GlobalVariable.RUN_INDICATOR is set to 'NO RUN', this test case will be skipped and the test suite will continue with the next one.

Setting the BaseX Document/Database context programmatically

I am attempting to set the database/document context programmatically via the Python API. My steps are as follows:
session = BaseXClient.Session("localhost", 1984, "admin", "admin")
query = session.query("//node")
query.context("doc('dbname')") # **NOT SURE HOW TO SET THE DB TO USE**
query.execute()
I already know that I can simply use the session object as follows and it works fine:
session.execute("xquery doc('dbname')//node/child")
But I am looking for a way to OPEN a database within the scope of the program call separate from the query string. I am not able to find the documentation to explicitly set the database prior to executing the query using the context object. I have looked at the source code for the python BaseXClient and there is context method for the Query() instance that is not well documented. I am attempting to use this to set the Database and not having much luck.
The context you have supplied is just a string. It is not evaluated. In a client server context it is difficult to see how one could pass in a database here.
I think your alternatives are to use the execute command to open a database before running the query. This will set the context. e.g.
var q = session.execute("open mydatabase",log.print)
var q = session.query("count(*)")
or use the query command bind command to pass parameters
var q = session.query("declare variable $db external; count(collection($db))")
q.bind("db", "mydatabase","",log.print);
q.execute(log.print);
Sorry these examples use Javascript and my BaseX Node client as I am not familiar with the Python API but I am sure the same applies in the Python API

Orchard cms token json

I would like to format a json payload in a workflow activity. I use the new {Text.JavaScriptEncode} to enclose my properties in {}. I should do it wrong because the tokens are not evaluated anymore. So if i use
{Text.JavaScriptEncode}{
"Courriel":{FormSubmission.Field:Courriel}
{Text.JavaScriptEncode}}
It ends with the following value:
{
"Courriel":{FormSubmission.Field:Courriel}
}
So the {FormSubmission.Field:Courriel} is not evaluated. If i don't specify {Text.JavaScriptEncode} before the first {, nothing is rendered (empty string).
I'm using Orchard 1.10.1.0
You might need to turn on the Tokenizers HashMode.
I haven't tested your token but I'm pretty sure the tokenizer tries to evaluate
this as a token and fails:
{"Courriel":{FormSubmission.Field:Courriel}
With hashMode enabled your code will look like this:
#{Text.JavaScriptEncode}{
"Courriel":#{FormSubmission.Field:Courriel}
#{Text.JavaScriptEncode}}

How to use common/shared "blocks" between cucumber features?

I'm new to cucumber, but enjoying it.
I'm currently writing some Frank tests, and would like to reuse blocks of cucumber script across multiple features - I'd like to do this a the cucumber level if possible (not inside the ruby).
For example, I might have 4 scripts that all start by doing the same login steps:
given my app has started
then enter "guest" in "user-field"
and enter "1234" in "password-field"
and press "login"
then I will see "welcome"
then *** here's the work specific to each script ***
Is there any way to share these first 5 lines across multiple scripts? Some kind of "include" syntax?
Generally there are 2 approaches:
Backgrounds
If you want a set of steps to run before each of the scenarios in a feature file:
Background:
given my app has started
then enter "guest" in "user-field"
and enter "1234" in "password-field"
and press "login"
then I will see "welcome"
Scenario: Some scenario
then *** here's the work specific to this scenario ***
Scenario: Some other scenario
then *** here's the work specific to this scenario ***
Calling steps from step definitions
If you need the 'block' of steps to be used in different feature files, or a Background section is not suitable because some scenarios don't need it, then create a high-level step definition which calls the other ones:
Given /^I have logged in$/ do
steps %Q {
given my app has started
then enter "guest" in "user-field"
and enter "1234" in "password-field"
and press "login"
then I will see "welcome"
}
end
Also, in this case I'd be tempted not to implement your common steps as separate steps at all, but to create a single step definition: (assuming Capybara)
Given /^I have logged in$/ do
fill_in 'user-field', :with => 'guest'
fill_in 'password-field', :with => '1234'
click_button 'login'
end
This lends a little bit more meaning to your step definitions, rather than creating a sequence of page interactions which need to be mentally parsed before you realise 'oh, this section is logging me in'.
A better approach is suggested to use ruby level "methods" to code reuse instead of nested steps from code maintenance and debugging perspective.
Here is the link to more detail:
Reuse Cucumber steps
Description
The following method proposes an alternative approach to one of the solutions described in Jon M's answer.
Namely, instead of calling nested steps inside step definitions, such common blocks of steps can be extracted into external .feature files which can be included into your feature file (in a manner of speaking).
How-to
1. Expose utility / helper methods to be able to run steps parsed from a .feature file
# features/support/env.rb
# expose Cucumber runtime
InstallPlugin do |_, registry|
runtime = registry.instance_variable_get('#registry').instance_variable_get('#runtime')
Cucumber.define_singleton_method(:runtime) { runtime }
end
# extend current World with methods to run dynamic (already parsed) steps
Before do
step_invoker = Cucumber::Runtime::SupportCode::StepInvoker.new(Cucumber.runtime.support_code)
define_singleton_method(:dynamic_steps) do |steps|
steps.each do |step|
dynamic_step(step)
end
end
define_singleton_method(:dynamic_step) do |step|
LOGGER.info("Running template step: #{step[:text]}")
step_invoker.step(step)
end
end
2. Create a template file which will contain the steps to be shared
# features/templates/my_profile.template.feature
#template
Feature: Steps to navigate to my_profile_page
Scenario: login_page
Given my app has started on "login_page"
And I enter "guest" in "user-field" on "login_page"
And I enter "1234" in "password-field" on "login_page"
And I press "login" on "login_page" and go to "welcome_page"
Scenario: welcome_page
Given that I am on "welcome_page"
And I click "my_profile_button" on "welcome_page" and go to "my_profile_page"
Scenario: my_profile_page
...
3. Create an utility module which will parse steps from a .feature file
# features/support/template_parser.rb
require 'gherkin/parser'
require 'gherkin/pickles/compiler'
module TemplateParser
class << self
def read_from_template(template_path, from: nil, till: nil)
pickles = load_template(template_path)
flow = construct_flow(pickles)
slice_flow(flow, from, till)
end
private
def load_template(template_path)
source = {
uri: template_path,
data: File.read(template_path),
mediaType: 'text/x.cucumber.gherkin+plain'
}
def source.uri
self[:uri]
end
gherkin_document = Gherkin::Parser.new.parse(source[:data])
id_generator = Cucumber::Messages::IdGenerator::UUID.new
Gherkin::Pickles::Compiler.new(id_generator).compile(gherkin_document, source)
end
def construct_flow(pickles)
pickles.to_h do |pickle|
[
pickle.name,
pickle.steps.map(&:to_h).map { |step| step[:argument] ? step.merge(step[:argument]) : step }
]
end
end
def slice_flow(flow, from, till)
raise NameError, "From step '#{from}' does not exist!" unless from.nil? || flow.keys.include?(from)
raise NameError, "Till step '#{till}' does not exist!" unless till.nil? || flow.keys.include?(till)
from_idx = from.nil? ? 0 : flow.keys.index(from)
till_idx = till.nil? ? -1 : flow.keys.index(till)
flow.slice(*flow.keys[from_idx...till_idx])
end
end
end
4. Create a step definition that will load this template and inject the specified steps dynamically at runtime
And('I complete the {string} template from the {string} until the {string}') do |template, from, till|
template_path = "features/templates/#{template}.template.feature"
flow = TemplateParser.read_from_template(
template_path,
from: from.empty? ? nil : from,
till: till.empty? ? nil : till
)
flow.each_value { |steps| dynamic_steps(steps) }
end
5. Use this step inside your main feature file, by declaring which blocks of steps to use
# features/tests/welcome.feature
Feature: User is welcomed
Scenario: Verify that user sees welcome text
Given I complete the 'my_profile' template from the 'login_page' until the 'my_profile_page'
Then I see 'welcome' on 'welcome_page'
6. Make sure you omit the #template .feature files from being run in your tests
$ bundle exec cucumber --tags ~#template
Limitations
Con:
This method exposes some internals of the private API of cucumber-ruby, which may change in future.
Con:
This is a non-standard way of sharing steps between feature files.
Helper methods are the preferred way to achieve this, as per FAQ.
Pro:
The common blocks of steps are syntax-highlighted, and have proper IntelliSense support in your editor of choice.
Pro:
You can encode entire "workflows" easily this way, allowing you to encode your workflow expectations in a DRY way.
Namely, you can reuse those workflow steps by completing the first part of a workflow, change a few things on a single page as per your test requirements, resume those workflow steps from the follow-up page, and add an appropriate verification at the end of the workflow that covers those test requirements.

Resources