Is it possible to transform a future type? - c++

Using a library that has a method like this one:
std::future<bool> action();
I find my self in a situation where I have to conform with project specific enum return types like:
enum Result { Ok, Failed, ConnectionDown, ServerError };
and the call site of action looks like this:
std::future<Result> act()
{
try {
return _actor->action(); // This returns a different type :(
// What to do here ??? ^
}
catch (ConnectionError const& e)
{
return std::make_ready_future<Result>(Result::ConnectionError);
}
catch (ServerError const& e)
{
return std::make_ready_future<Result>(Result::ServerError);
}
}
so essentially the library doesn't have specific return codes for error cases, they are rather emitted as exceptions. Handling that is easy because I can construct ready futures with the appropriate value. The problem (ironically) is with the non exceptional path, where the library's std::future<bool> has to be transformed to std::future<Result>.
It's pointless to .get() the result and construct a ready future based on its value (true -> Ok, false -> Failed) because this way I'm removing asynchronicity from my function. Is there a better way to handle this?

Waiting for continuation function (std::experimental::future::then)
, you probably want something like:
std::future<Result> act()
{
return std::async([&](){
try {
if (_actor->action().get()) {
return Result::Ok;
} else {
return Result::Failed;
}
}
catch (ConnectionError const& e) {
return Result::ConnectionError;
}
catch (ServerError const& e) {
return Result::ServerError;
}
});
}

Related

Cast exception when mocking kotlin lambda callbacks in Mockk

I am having some trouble mocking callback functions with Mockk.
I am trying to mock a task success listener that is called like this:
collection
.add(Item())
.addOnSuccessListener {
update(collection.document(it.id))
}
Where the java signature for the callback would look like this:
public interface OnSuccessListener<T> {
void onSuccess(T var1);
}
and the signature for addOnSuccessListener looks like this
public abstract Task<DocumentReference> addOnSuccessListener(#NonNull OnSuccessListener<DocumentReference> var1);
My mock looks like this:
every { documentReferenceTask.addOnSuccessListener(any()) } answers {
firstArg<(DocumentReference) -> Unit>().onSuccess(documentReference)
value
}
I have also tried:
every { documentReferenceTask.addOnSuccessListener(any()) } answers {
firstArg<OnSuccessListener<DocumentReference>>().invoke(documentReference)
value
}
Either way, I am receiving a cast exception like:
java.lang.ClassCastException: com.package.MyClass$addProduct$1 cannot be cast to kotlin.jvm.functions.Function1
Oops, I was misreading the error.
every { documentReferenceTask.addOnSuccessListener(any()) } answers {
firstArg<OnSuccessListener<DocumentReference>>().invoke(documentReference)
value
}
This method works, the cast exception was from the second line. The correction looks like
every { documentReferenceTask.addOnSuccessListener(any()) } answers {
firstArg<OnSuccessListener<DocumentReference>>().invoke(documentReference)
**documentReferenceTask**
}

Unable to check exception type in google test

I'm unable to check the exception throw by my code in gtests. Here's a snippet of the test suite which runs the test:
EXPECT_THROW({
try{
// Insert a tuple with more target columns than values
rows_changed = 0;
query = "INSERT INTO test8(num1, num3) VALUES(3);";
txn = txn_manager.BeginTransaction();
plan = TestingSQLUtil::GeneratePlanWithOptimizer(optimizer, query, txn);
EXPECT_EQ(plan->GetPlanNodeType(), PlanNodeType::INSERT);
txn_manager.CommitTransaction(txn);
TestingSQLUtil::ExecuteSQLQueryWithOptimizer(
optimizer, query, result, tuple_descriptor, rows_changed, error_message);
}
catch (CatalogException &ex){
EXPECT_STREQ("ERROR: INSERT has more target columns than expressions", ex.what());
}
}, CatalogException);
I'm pretty sure that CatalogException is thrown. I even tried getting the details of the thrown exception by outputting it to cerr, and it showed Exception Type: Catalog.
This is not a duplicate question, I searched for answers on SO and I'm not using new in my code which throws the error. Here's the snippet which does that:
if (columns->size() < tup_size)
throw CatalogException(
"ERROR: INSERT has more expressions than target columns");
Finally, here's the definition of CatalogException:
class CatalogException : public Exception {
CatalogException() = delete;
public:
CatalogException(std::string msg) : Exception(ExceptionType::CATALOG, msg) {}
};
The idea from EXPECT_THROW is, that the macro catches the exception. If you catch the exception by yourself, gmock don't now anything about a thrown exception.
I suggest to just write the statement into the EXPECT_THROW, which actually trigger the exception. Everything else can be written before.
For example:
TEST(testcase, testname)
{
//arrange everything:
//...
//act + assert:
EXPECT_THROW(TestingSQLUtil::ExecuteSQLQueryWithOptimizer( optimizer, query, result,
tuple_descriptor, rows_changed, error_message)
,CatalogException);
}
I assume, that TestingSQLUtil::ExecuteSQLQueryWithOptimizer is trigger the thrown exception.
addition:
I tried to rebuild your exception hierarchy. This example works for me very well. The test passes, which means the exception is thrown.
enum class ExceptionType
{
CATALOG
};
class Exception {
public:
Exception(ExceptionType type, std::string msg) {}
};
class CatalogException : public Exception {
CatalogException() = delete;
public:
CatalogException(std::string msg) : Exception(ExceptionType::CATALOG, msg) {}
};
void testThrow() {
throw CatalogException( "ERROR: INSERT has more expressions than target columns");
}
TEST(a,b) {
EXPECT_THROW( testThrow(), CatalogException);
}

TypeScript Generic Collection: List

I am trying to learn TypeScript, and need some advice on implementing generic collection types. I put the dictionary and HashSet in another question, here I'd like any advice on my list type.
Especially the ForEach-Operation looks a bit strange. I think I found it in another question here, and "improved" by returning true or false to give feedback if the iteration was stopped early or completed.
import { IForEachFunction } from "./IForEachFunction"
export class List<T> {
private _items: Array<T>;
public constructor() {
this._items = [];
}
public get Count(): number {
return this._items.length;
}
public Item(index: number): T {
return this._items[index];
}
public Add(value: T): void {
this._items.push(value);
}
public RemoveAt(index: number): void {
this._items.splice(index, 1);
}
public Remove(value: T): void {
let index = this._items.indexOf(value);
this.RemoveAt(index);
}
public ForEach(callback: IForEachFunction<T>): boolean {
for (const element of this._items) {
if (callback(element) === false) {
return false;
}
}
return true;
}
}
The ForEach-Iteration relies on an interface from another file:
export interface IForEachFunction<T> {
(callback: T): boolean | void;
}
You would use my list and the ForEach-Method like this:
let myList: List<a_type> = new List<a_type>();
let completed: boolean = myList.ForEach(xyz => {
// do something with xyz
return false; // aborts the iteration
return true; // continues with the next element
});
if (completed) // we can see what happened "during" the iteration
I think this is not bad, but I'd appreciate any input. I am not sure if I use the === correctly.
Another question which I really like to know: How could I define a function with the interface IForEachFunction? I do not really "re-use" that interface visibly, I always declare an anonymous method as shown above. If I wanted to call a method having the interface definition, is that possible?
Thanks!
Ralf
One problem I see is that you have an interface instance:
callback: IForEachFunction<T>
This contains a method called
callback()
But you only call callback once. You would have call callback() method inside your interface:
callback.callback()
Also your code looks like it is inspired by C# or Java. In TypeScript you would often just use an array. This simplifies certain code constructs.

How to specify return policy for object returned as part of a tuple in boost python

I have a function that creates a C++ object. Before the refactor, I was returning a pointer from the C++ function, and in the boost python wrapper declaration, I would use boost::python::return_value_policy<boost::python::manage_new_object>. Something like this:
MyObject* create_object_from_description(std::string& description)
{
...
return myObject;
}
BOOST_PYTHON_MODULE(pymol) {
boost::python::def("create_obj_from_desc", create_object_from_description,
(boost::python::arg("description")),
"",
boost::python::return_value_policy<boost::python::manage_new_object>()
);
Now I need to return more than just the object, but also some error messages, and the refactor basically changes the C++ function to let it return a tuple:
boost::python::tuple create_object_from_description(std::string& description)
{
...
return boost::python::make_tuple(myObject, errmsg);
}
How should I specify the return policy with this change?
I don't think that this is possible. What you probably need to do is change the function signature and re-wrap the function in python. Like this:
boost::python::tuple create_object_from_description(std::string& description,
MyObject& myObject)
{
myObject = mo;
return errmsg
}
Then in python have a function like this:
def create_object_from_description(description):
mo = MyObject()
errmsg = pymol.create_object_from_description(description, mo)
return mo, errmsg
Of course, what you should REALLY do is throw an exception. Boost::python does a very nice job of turning c++ exceptions in to python exception and vice-versa

Is this 4-tier architecture good?(Exception handling is important for me :)

I have this layers in my application:
Entities
Database (with Entities reference)
Business (with database and Entities references)
User Interface (with Business and Entities references)
Here is an example of my codes:
UserDAL class in database layer:
public class UsersDal
{
databaseDataContext db;
public UsersDal()
{
try
{
db = new databaseDataContext(ConnectToDatabase.GetConnectionString());
}
catch (Exception ex)
{
throw ex;
}
}
public List<User> GetAllUsers()
{
try
{
return (from u in db.Users select u).ToList();
}
catch (Exception ex)
{
throw ex;
}
}
And so on...
In the UserBLL class in Business layer i write like this:
public class UsersBll
{
UsersDal user;
public UsersBll()
{
try
{
user = new UsersDal();
}
catch(Exception ex)
{
throw new ProjectException(Errors.CannotCreateObject, ex);
}
}
public List<User> GetAllUsers()
{
try
{
return user.GetAllUsers();
}
catch(Exception ex)
{
throw new ProjectException(Errors.CannotReadData, ex);
}
}
And in UI i write:
private void GetUsers()
{
try
{
UsersBll u = new UsersBll();
datagrid.DataSource = u.GetAllUsers();
}
catch(ProjectException ex)
{
MessageBox(ex.UserMessage);// and also can show ex.InnerException.Message for more info
}
}
Well, I use a ProjectException named class to produce an error contain a BLL created message by me and an Exception message that the OS automatically manipulate.
Also i create an enum of possible errors and a dictionary
here is some details about it:
namespace Entities
{
public enum Errors
{
CannotCreateObject,
CannotReadData,
CannotAdd,
CannotEdit,
CannotDelete,...
}
[global::System.Serializable]
public class ProjectException : Exception
{
public ProjectException(Errors er, Exception ex)
: base(errors[er], ex)
{
currentEx = er;//er is Errors enum
}
static ProjectException()
{
errors = new Dictionary<Errors, string>();
errors.Add(Errors.CannotCreateObject, "the application cannot connect to database!");
errors.Add(Errors.CannotReadData, "the application cannot read data from database"); //...
}
public string UserMessage
{
get
{
try
{
return errors[currentEx];
}
catch
{
return "Unknown error!";
}
}
}
Is this good?
it work for me fine.
what's your idea?
It is almost always wrong within a catch (ex) to do a throw ex;. Either just do throw; or else throw new whateverException("someMessage", ex);. The decision of whether to use the former form or the latter generally depends upon whether you are crossing an application layer. If an AcmeServerDatabaseWrapper, which derives from DatabaseWrapper type, is performing a query when an AcmeDatabaseTableNotFoundException is thrown, it should catch that and rethrow it as a DatabaseWrapperTableNotFoundException (if such a type exists) or as a DatabaseWrapperOperationFailedException. Client code which has an object derived from DatabaseWrapper should be able to know what types of exceptions that object will throw, without having to know what type of object it is. Any exception which escapes from the database layer without being wrapped is an exception the client code is unlikely to be able to handle sensibly, but might handle erroneously (thinking it occurred in a context other than where it actually happened).