Test an infinite loop in minitest - minitest

I have a job named ActivityJob which fetches an user's github public activities.
class ActivityJob < ActiveJob::Base
queue_as :git
def perform(user)
begin
#fetch github activities for a user using user's auth_token
activities = ActivitiesFetcher.new(user).fetch
# process the retrieved activities.
rescue Github::Error::NotFound
#user is not present. ignore and complete the job.
rescue Github::Error::Unauthorized
#auth token is invalid. re-assign a new token on next sign in
user.auth_token = nil
user.save
# refresh_gh_client gets a new client using a random user's auth_token
user.refresh_gh_client
retry
rescue Github::Error::Forbidden
# Probably hit the Rate-limit, use another token
user.refresh_gh_client
retry
end
end
end
The method refresh_gh_client gets a random user from db and uses its auth_token to create an new gh_client. the new gh_client is assigned to the current user. This is working fine. In test cases, I am using mocha to stub the method calls.
class ActivityJobTest < ActiveJob::TestCase
def setup
super
#user = create :user, github_handle: 'prasadsurase', auth_token: 'somerandomtoken'
#round = create :round, :open
clear_enqueued_jobs
clear_performed_jobs
assert_no_performed_jobs
assert_no_enqueued_jobs
end
test 'perform with Github::Error::Unauthorized exception' do
User.any_instance.expects(:refresh_gh_client).returns(nil)
ActivitiesFetcher.any_instance.expects(:fetch).raises(Github::Error::Unauthorized, {})
ActivityJob.perform_now(#user, 'all', #round)
#user.reload
assert_nil #user.auth_token
end
end
The problem is that the 'retry' in the job calls the ActivitiesFetcher breaking the expectation that it was supposed to be called only once.
:
unexpected invocation: #<AnyInstance:User>.refresh_gh_client()
unsatisfied expectations:
- expected exactly once, invoked twice: # <AnyInstance:User>.refresh_gh_client(any_parameters)
- expected exactly once, invoked twice: #<AnyInstance:ActivitiesFetcher>.fetch

Make an interface for the ActivitiesFetcher behavior you need. You create an implementation of the interface used only for testing that deals with the idiosyncrasies of testing.

Related

Why does transact and wait behave differently when within a function is behaving different?

Within my project I intend to send large volumes of transactions therefore for simplicity I am building a wrapper function for the following functions to be executed together: contractName.functions.functionName(params).transact() and w3.eth.wait_for_transaction(tx_hash). However when I write the functions transact_and_wait with the above implemented within in the transactions do not get executed!
Implementation of Transact and wait
def transact_and_wait(contract_function, transaction_params= {"gas": 100000}):
# Send the transaction
if transaction_params != {"gas": 100000}:
transaction_params["gas"] = 100000
transaction_hash = contract_function.transact(transaction_params)
# Wait for the transaction to be mined
transaction_receipt = w3.eth.wait_for_transaction_receipt(transaction_hash)
return transaction_receipt
Where it is called via: Transact_and_wait(contractName.functions.functionName(account.address))
For example this should set the a role for a user defined via index 1
However when I call. print(contractName.functions.stateVariable(account.address).call()) it returns 0
If i do the same process above but not within a functions:
tx_hash = contractName.functions.functionName(account.address).transact({"gas": 100000}))
transaction_receipt = w3.eth.wait_for_transaction_receipt(tx_hash)
Then I can call the same getter: print(contractName.functions.stateVariable(account.address).call()
It returns 1.

Need to set JMS_IBM_LAST_MSG_IN_GROUP property to true for IBM MQ testing using JMeter

I am testing IBM MQ using JMeter and able to establish the connection with queue to send requests over it. However, I need to set "JMS_IBM_LAST_MSG_IN_GROUP" property as true for one of the message but unable to do so. I am using below piece of code while sending request or trying to set the property to true but it remains set to it's default value i.e. false when I am checking in backend. Any clue what I am missing here.
Note: Connection is being established in another sampler and making use of that connection here. This code is working fine to send any request, just that property is not getting set to true.
import java.time.Instant
import com.ibm.msg.client.jms.JmsConstants
def sess = System.getProperties().get("Session")
def destination = System.getProperties().get("Destination")
def producer = sess.createProducer(destination)
def rnd = new Random(System.currentTimeMillis())
def payload = String.format('${groupid}|${sequencenumber}|rest of the payload|')
def msg = sess.createTextMessage(payload)
println('Payload --> ' + payload)
msg.setBooleanProperty(JmsConstants.JMS_IBM_LAST_MSG_IN_GROUP,true)
def start = Instant.now()
producer.send(msg)
def stop = Instant.now()
producer.close()
SampleResult.setResponseData(msg.toString())
SampleResult.setDataType( org.apache.jmeter.samplers.SampleResult.TEXT)
SampleResult.setLatency( stop.toEpochMilli() - start.toEpochMilli())
Your code does not include anything to set the Group ID or sequence number. I assume we have all the relevant code shown, in which case, I think you are missing code something along these lines:
msg.setStringProperty("JMSXGroupID", groupid);
msg.setIntProperty("JMSXGroupSeq", sequencenumber);
As per JMS_IBM_LAST_MSG_IN_GROUP chapter of IBMMQ documentation
This property is ignored in the publish/subscribe domain and is not relevant when an application connects to a service integration bus.
In general it's not necessary to use this property, you can come up with your own custom one, i.e. for the producer:
msg.setBooleanProperty("X_CUSTOM_PROPERTY_LAST_MESSAGE",true)
and for the consumer:
msg.getBooleanProperty("X_CUSTOM_PROPERTY_LAST_MESSAGE")
More information: IBM MQ testing with JMeter - Learn How
Sharing as it might help someone else. Was able to set the property to true by making below changes, rest of the code is same as mentioned in original question
import com.ibm.msg.client.wmq.WMQConstants
def gid=String.format('${groupid}')
def msg = sess.createTextMessage()
println('Payload --> ' + payload)
msg.setStringProperty(WMQConstants.JMSX_GROUPID,gid)
msg.setBooleanProperty(WMQConstants.JMS_IBM_LAST_MSG_IN_GROUP,true)
msg.text=payload

Setting the current test insertion within the DUT model

We have evolved our Origen usage such that we have a params file and a flow file for each test module (scan, mbist, etc.). We are now at the point where we need to take into account the test insertion when handling the DUT model and the test flow generation. I can see here that using a job flag is the preferred method for specifying test insertion specifics into the flow file. And this video shows how to specify a test insertion when simulating the test flow. My question is how can a test insertion be specified when not generating a flow, only loading params files into the DUT model? Take this parameter set that defines some test conditions for a scan/ATPG test module.
scan.define_params :test_flows do |p|
p.flows.ws1.chain = [:vmin, :vmax]
p.flows.ft1.chain = [:vmin, :vmax]
p.flows.ws1.logic = [:vmin, :vmax]
p.flows.ft1.logic = [:vmin]
p.flows.ws1.delay = [:pmax]
p.flows.ft1.delay = [:pmin]
end
You can see in the parameter set hierarchy that there are two test insertions defined: 'ws1' and 'ft1'. Am I right to assume that the --job option only sets a flag somewhere when used with the origen testers:run command? Or can this option be applied to origen i, such that just loading some parameter sets will have access to the job selected?
thx
There's no built-in way to do what you want here, but given that you are using parameters in this example the way I would do it would be to align your parameter contexts to the job name:
scan.define_params :ws1 do |p|
p.flows.chain = [:vmin, :vmax]
p.flows.logic = [:vmin, :vmax]
p.flows.delay = [:pmax]
end
scan.define_params :ft1 do |p|
p.flows.chain = [:vmin, :vmax]
p.flows.logic = [:vmin]
p.flows.delay = [:pmin]
end
There are various ways to actually set the current context, one way would be to have a target setup per job:
# target/ws1.rb
MyDUT.new
dut.params = :ws1
# target/ft1.rb
MyDUT.new
dut.params = :ft1
Here it is assuming that the scan object is configured to track the context of the top-level DUT - http://origen-sdk.org/origen//guides/models/parameters/#Tracking_the_Context_of_Another_Object

post test execution callbacks available?

I am looking to apply a callback post test execution that will check for an alarm flag. I don't see any listed here so I then checked the test interface and only see what looks like a flow level callback:
# This will be called at the end of every flow or sub-flow (at the end of every
# Flow.create block).
# Any options passed to Flow.create will be passed in here.
# The options will contain top_level: true, whenever this is called at the end of a
# top-level flow file.
def shutdown(options = {})
end
We need the ability to check the alarm flags after every test but still apply a common group ID to a list of tests like this:
group "func tests", id: :func do
[:minvdd, :maxvdd].each do |cond|
func :bin1_1200, ip: :cpu, testmode: :speed, cond: cond
end
end
Here is an example of the V93K alarm flow flag:
thx!
It is common when writing interfaces to funnel all test generation methods through a common single method to add them to the flow:
def func(name, options = {})
t = test_suites.add(name)
t.test_method = test_methods.origen.functional_test(options)
add_to_flow(t, options)
end
def para(name, options = {})
t = test_suites.add(name)
t.test_method = test_methods.origen.parametric_test(options)
add_to_flow(t, options)
end
def add_to_flow(test_obj, options = {})
# Here you can do anything you want before adding each test to the flow
flow.test(test_obj, options)
# Here you can do anything you want after adding each test to the flow
end
So while there is no per-test callback, you can generally achieve whatever you wanted to do with one via the above interface architecture.
EDIT:
With reference to the alarm flag flow structure you want to create, you would code it like this:
func :some_func_test, id: :sft1
if_failed :sft1 do
bin 10, if_flag: "Alarm"
bin 11, unless_flag: "Alarm"
end
Or, if you prefer, this is equivalent:
func :some_func_test, id: :sft1
bin 10, if_flag: "Alarm", if_failed: :sft1
bin 11, unless_flag: "Alarm", if_failed: :sft1
At the time of writing, that will generate something logically correct but with a sub-optimal branch structure.
In the next release that will be fixed, see the test case that has been added here and the output it generates here.
You can call all of the flow control methods from the interface the same way you can from within the flow, so you can inject such conditions in the add_to_flow method if you want.
Note also that in the test case both if_flag and if_enable are used. if_enable should generally be used if the flag is something that would be set at the start of the flow (e.g. by the operator) and would not change. if_flag should be used if it is a flag that is subject to modification by the flow at runtime.

Custom type/provider not ensurable

I'm trying to create a new custom type/provider but not ensurable.
I've already checked the exec and augeas types, but I couldn't figure out clearly how exactly the integration between type and provider work when we don't define the ensurable mode.
Type:
Puppet::Type.newtype(:ptemplates) do
newparam(:name) do
desc ""
isnamevar
end
newproperty(:run) do
defaultto 'now'
# Actually execute the command.
def sync
provider.run
end
end
end
Provider:
require 'logger'
Puppet::Type.type(:ptemplates).provide(:ptemplates) do
desc ""
def run
log = Logger.new(STDOUT)
log.level = Logger::INFO
log.info("x.....................................")
end
But I don't know why the provider is being executed twice
root#puppet:/# puppet apply -e "ptemplates { '/tmp': }" --environment=production
Notice: Compiled catalog for puppet.localhost in environment production in 0.12 seconds
I, [2017-07-30T11:00:15.827103 #800] INFO -- : x.....................................
I, [2017-07-30T11:00:15.827492 #800] INFO -- : x.....................................
Notice: /Stage[main]/Main/Ptemplates[/tmp]/run: run changed 'true' to 'now'
Notice: Applied catalog in 4.84 seconds
Also, I had to define the defaultto to force the execution of the provider.run method.
What am I missing ?
Best Regards.
First you should spend some time reading this blog http://garylarizza.com/blog/2013/11/25/fun-with-providers/ and the two following by Gary Larizza. It gives a very good introduction to puppet type/providers.
Your log is being executed twice because of your def sync in the type that calls the run define, second when puppet tries to determine the value of your run property.
In order to write a type/provider that is not ensurable you need to do something like:
Type:
Puppet::Type.newtype(:ptemplates) do
#doc = ""
newparam(:name, :namevar => true) do
desc ""
end
newproperty(:run) do
desc ""
newvalues(:now, :notnow)
defaultto :now
end
end
Provider:
Puppet::Type.type(:ptemplates).provide(:ruby) do
desc ""
def run
#Do something to determine if run value and is now or notnow and return it
end
def run= value
#Do something to set the value of run
end
end
Note that all type providers must be able to determine the value of the property and be able to set it. The difference between an ensurable and a not ensurable type/provider is that the ensurable type/prover is able to create and destroy it, fx remove an user or add an user. A type/provider that is not ensurable is not able to create and destroy the property, fx selinux, you can set its value, but you cannot remove selinux.

Resources