I am working with WebAssembly and try to make an HTTPS request from C++. I have seen the solution of Emscripten FETCH API and tried to use it.
To test it, I created a Test class where I send the request like this :
void Test::sendRequest() {
emscripten_fetch_attr_t attr;
emscripten_fetch_attr_init(&attr);
strcpy(attr.requestMethod, "GET");
attr.attributes = EMSCRIPTEN_FETCH_LOAD_TO_MEMORY;
attr.onsuccess = &Test::onSuccess;
attr.onerror = &Test::onError;
emscripten_fetch(&attr, "http://127.0.0.1:5000/");
}
And my onSuccess callback look like this :
void Test::onSuccess(struct emscripten_fetch_t *fetch) {
printf("Finished downloading %llu bytes from URL %s.\n", fetch->numBytes, fetch->url);
setText(QString::fromUtf8(fetch->data));
emscripten_fetch_close(fetch); // Free data associated with the fetch.
}
But, when I try to compile I have an error saying :
error: assigning to 'void (*)(struct emscripten_fetch_t *)' from incompatible type 'void
(Test::*)(struct emscripten_fetch_t *)'
attr.onsuccess = &Test::onSuccess;
^~~~~~~~~~~~~~~~
It seems that I can't put the callback function in the class, but I need to access the class in order to modify the text attribute of the instance with the response.
I tried to define the Test class with the Singleton pattern and to remove the callback function from the class. With this method I can modify the text attribute getting the unique instance of the class but I would like to put callback function in the class directly if possible.
You can't use a non-static member function as a callback directly.
However, most callback interfaces have a "user data" field somewhere for communicating back to the originator.
emscripten_fetch_attr_t has a void* userData member where you can store any pointer you want.
This pointer is passed as userData in the argument to the callbacks, and you just need to cast it back to the correct type.
So you can use a free function as a wrapping callback, with the object as "user data":
void onSuccess(struct emscripten_fetch_t *fetch) {
auto test = static_cast<Test*>(fetch->userData);
test->onSuccess(fetch);
}
void Test::sendRequest() {
emscripten_fetch_attr_t attr;
emscripten_fetch_attr_init(&attr);
strcpy(attr.requestMethod, "GET");
attr.attributes = EMSCRIPTEN_FETCH_LOAD_TO_MEMORY;
attr.userData = this;
attr.onsuccess = onSuccess;
// ...
And make sure that the object is alive when the callback fires.
Related
Assume I got a some Message class object which has nlohmann json as private member and public getter:
class Message{
public:
nlohmann::json getJson() { return json_;}
...
private:
nlohmann::json json_;
...
};
Also there is a class that publishes the message
ex:
class Foo {
public:
publish(const Message& message)
...
};
In the test I am mocking the Foo::publish method and in some scenario I want to check if json_["key1"]["key2"] value is different than "" (empty string)
EXPECT_CALL(
*foo_mock_pointer,
publish(x) // x is the unknown code
);
For checking the value of the json object I guess it will be enough:
testing::Contains(testing::Pair("key1", testing::Pair("key2"), testing::Ne("")))
But I cant figure out how to get the json from Message object which is the argument of the mocked method.
IIUC, it looks like you want to check something about the argument that is passed to your mock function.
You can use SaveArg to save that argument inside a variable and then check its value later:
Message message;
EXPECT_CALL(
*foo_mock_pointer,
publish(x) // x is the unknown code
).WillOnce(DoAll(SaveArg<0>(&message), Return(/*Whatever you want to return*/)));
// Call your class-under-test API here
// ...
// Now check the message:
EXPECT_THAT(message.getJson(), /*Insert your matcher here*/);
See here for more info: http://google.github.io/googletest/gmock_cook_book.html#SaveArgVerify
I have a class named Reciever that has a function called recieve(const Event *), where Event inherits from BaseEvent. I want to create a bind to a specific instance of that class. The instance is called rec. To do this I use:
void(Reciever::*func)(const Event *) = &Reciever::recieve;
auto recievePtr = std::bind(func, &rec, std::placeholders::_1);
However, when I try to store this in a vector, I have to specify an std::function that takes a BaseEvent as the input, not an Event, like so:
std::vector<std::function<void(const BaseEvent*)>>
How can I cast recievePtr so I can store it properly in the vector? Is this even possible? The issue with using a function pointer to a BaseEvent is that the Reciever can have multiple recieve() methods with different derived classes all based on BaseEvent
You can try something along the following. This compiled and ran fine on my machine. Visual Studio targeting platform toolset v120.
Reciever rec;
std::vector<std::function<void(const BaseEvent*)>> vector;
vector.push_back(
[&rec](const BaseEvent* event)
{
rec.recieve(static_cast<const Event*>(event));
});
vector.push_back(
[&rec](const BaseEvent* event)
{
rec.recieve(static_cast<const EventD*>(event));
});
const BaseEvent* e = new Event();
const BaseEvent* d = new EventD();
vector[0](e);
vector[1](d);
I am using this module hierarchy :
Node: {udpApp[0]<->udp<->networkLayer->wlan[0]} and wlan[0]: {CNPCBeacon<->mac<->radio}
With some ini parameter for udpApp as:
I have given some initial parameter in the ini file for udpApp as :
**.host*.numUdpApps = 2
**.host*.udpApp[0].typename = "UDPBasicApp"
**.host*.udpApp[0].destAddresses = "gw1"
**.host*.udpApp[0].startTime = 1.32s
**.host*.udpApp[0].stopTime = 1.48s
But at run time I want to change the startTime and stopTime for udpAPP[0] through CNPCBeacon module.
Hence I changed CNPCBeacon.cc as:-
cModule* parentmod = getParentModule();
cModule* grantParentmod = parentmod->getParentModule();
cModule* udpmod = grantParentmod->getSubmodule("udpApp",0);
double varHoldingStartTime = udpmod->par("startTime").doubleValue();
double varGoldingStopTime = udpmod->par("stopTime").doubleValue();
varHoldingStartTime = SIMTIME_DBL(4.2);
varGoldingStopTime = SIMTIME_DBL(4.5);
udpmod->par("startTime").setDoubleValue(varHoldingStartTime);
udpmod->par("stopTime").setDoubleValue(varGoldingStopTime);
EV<<"New start and stop time is "<<udpmod->par("startTime").str()<<"\t"<<udpmod->par("stopTime").str()<<endl;`
Which successfully change the parameters. However it doesn't initiate the udpApp[0] module again. So I try to use dynamic casting of this module as:
UDPBasicApp* udpBasicMod = dynamic_cast<UDPBasicApp*>(udpmod);
sendTimer = new cMessage("sendTimer");
scheduleAt(iniSchduleTime, sendTimer);
and it resulted in following error:-
error in module (CNPCBeacon) BSoneNode.gw1.wlan[0].CNPCBeacon (id=23) at event #1496, t=4: scheduleAt() of module (UDPBasicApp)BSoneNode.gw1.udpApp[0] called in the context of module (CNPCBeacon)BSoneNode.gw1.wlan[0].CNPCBeacon: method called from the latter module lacks Enter_Method() or Enter_Method_Silent()?.
Is there also any other way to instantiate a module through other sub module.
Thanks for this help.
The solution for reinitializing a module (target module) through another module (requesting module) is creating handleParamterChange() function in target module. handleParameterChange() is used to reread the changed parameter at tun time. However it won't start scheduleAt() event to reinitialize the event for the target module. So I just added the scheduleAt() event in this function as :
void UDPBasicApp:: handleParameterChange(const char* parname)
{
if(parname)
{
if((strcmp(parname, "startTime")==0) &&
(startTime != par("startTime").doubleValue())
startTime = par("startTime").doubleValue();
if(strcmp(parname,"stopTime")==0)&&
(stopTime != par("stopTime").doubleValue())
{
stopTime = par("stopTime").doubleValue();
selfMsg->setKind(START);
scheduleAt((simtime_t)(startTime), selfMsg);
}
}
Note here that selfMsg is defined in the initialize function of UdpBasciApp.cc in INET framework.
I am a bit lost in the hierarchy and relation between your modules and sub-modules, however I think if your want to create (or re-create) a module dynamically you could use the built-in approach suggested by OMNeT++: https://omnetpp.org/doc/omnetpp/manual/usman.html#sec186
Maybe you could use the one-liner directly once you have (re-)defined the parameter values:
cModuleType *moduleType = cModuleType::get("foo.nodes.WirelessNode");
cModule *mod = moduleType->createScheduleInit("node", this);
On the other hand you error message complains about: Enter_Method() and/or Enter_Method_Silent()
These macros should be used in case that you try to call a function of a module (example X::get()) from within another module:
Y::doSmthWithXsGet()
{
x->get();
}
For this to work Enter_Method() (or Enter_Method_Silent()) has to be written in the beginning of X::get()
X::get()
{
Enter_Method();
/* rest of the code */
}
You can read Direct Method Calls section of the OMNeT++ userman to see what that means.
The weird thing is that you are getting this error for the scheduleAt() method, which is a method which belongs to the fundamental OMNeT++ class cSimpleModule. That means, in order to use this method in your class you will have to inherit from cSimpleModule in your class definition.
Maybe simply doing something like:
class MyCurrentClass: public cSimpleModule
{
/* further class definition */
};
... could solve your prob.
I'm writing a unit test for a REST Service connector which is using a third party tool called Httpful.
Because I do not want to send real requests to the server, I mocked the "send" method from Httpful\Request:
$mockedRequest = $this->getMock('Httpful\Request', array('send'), array(), '', false);
$mockedRequest->expects($this->once())->method('send');
This works fine, but the Request Class has a method called expects itself, which I use in my actual code to define the acceptable mime type of the response.
$this
->getRequest('GET')
->uri(ENDPOINT . $configurationId) //by default this returns a Request Object (now mocked request)
->expects('application/json') //crashes ...
->send();
When the code gets executed, I get the following error (which is understandable):
Argument 1 passed to Mock_Request_938fb981::expects() must implement interface PHPUnit_Framework_MockObject_Matcher_Invocation, string given
Is there something like a configurable prefix for methods coming from the Mock Class like "expects"?
I don't think that you will be able to do that using the PHPUnit_MockObject class. But you can code your own and use that instead.
class MockRequest extends \Httpful\Request {
public $isSendCalled = false;
public $isUriCalled = false;
public $isExpectsCalled = false;
public function uri($url) {
if($url !== '<expected uri>') {
throw new PHPUnit_Framework_AssertionFailedError($url . " is not correct");
}
$this->isUriCalled = true;
return $this;
}
public function expects($type) {
if($type !== 'application/json') {
throw new PHPUnit_Framework_AssertionFailedError($type . " is not correct");
}
$this->isExpectsCalled = true;
return $this;
}
public function send() {
$this->isSendCalled = true;
}
}
Your line for creating the mock then just becomes:
$mockedRequest = new MockRequest();
If the constructor fo
Then in your test you can verify that the methods are called with
$this->assertTrue($mockedRequest->isSendCalled);
$this->assertTrue($mockedRequest->isUriCalled);
$this->assertTrue($mockedRequest->isExpectsCalled);
This isn't a very dynamic mock but it will pass the type hinting and does your check for you. I would create this mock in the same file as your test (though be careful about not accidentally redefining this class elsewhere in your test suite). But it gets you around the problem of having expects being overridden.
The PHPUnit_Framework_MockObject_MockObject is an interface that sets the signature for expects() also which your class wouldn't meet and so there would be an error if you were able to rename the method.
https://github.com/sebastianbergmann/phpunit-mock-objects/blob/master/src/Framework/MockObject/MockObject.php
I have a simple webservice returning object list of books. I am trying to take this collection with aducentes web service class, but I get the type error:
TypeError: Error #1010: A term is undefined and has no properties.
Can anyone help to pull object into
array and trace the result?
import alducente.services.WebService;
import flash.events.*;
var ws:WebService = new WebService();
ws.addEventListener(Event.CONNECT, connected);
ws.connect("http://localhost:8732/Design_Time_Addresses/TestService/Service1/?wsdl");
ws.cacheResults = true;
var initTime:Number;
function connected(evt:Event):void{
// var books:Array=ws.IBookService.GetBooks();
// trace(books[0]);
var obj:Object=ws.IBookService.GetBooks();
// var obj:Object=ws.IBookService.GetBooks();
// trace(obj[0].toString());
}
Just thought of something else... In the version of WebService I used a while back, you have to specify a resultHandler function with each method call:
function connected(evt:Event):void{
ws.IBookService.GetBooks( getBooksResultHandler );
}
function getBooksResultHandler( resultXML : XML ) : void {
doStuffWith(resultXML);
}
The result will be passed to the handler you've passed as a parameter.