I am trying to write a widget test for my flutter screens which are built with bloc. But I am not able to access any of my widget through the test. Following is my widget test code:
FeedbackListBloc feedbackListBloc;
FeedbackListRepository feedbackListRepository;
PrefStore prefStore;
group('login error handling', () {
feedbackListRepository = MockFeedbackListRepository();
prefStore = MockPrefStore();
feedbackListBloc = FeedbackListBloc(feedbackListRepository,prefStore);
testWidgets('validate Feedback List widget', (WidgetTester tester) async {
Widget testWidget = new MediaQuery(
data: MediaQueryData(),
child: MaterialApp(home: FeedbackList(feedbackListBloc: feedbackListBloc))
);
Widget localizedWidget = Localizations(
delegates: [
AppLocalizations.delegate,
// Built-in localization of basic text for Material widgets
GlobalMaterialLocalizations.delegate,
// Built-in localization for text direction LTR/RTL
GlobalWidgetsLocalizations.delegate,
],
locale: Locale('en'),
child: testWidget,
);
await tester.pumpWidget(localizedWidget);
await tester.pumpAndSettle();
expect(find.byIcon(Icons.add), findsOneWidget);
});
});
I am always getting following error in my expect method:
test/widget_test/dashboard/feedback/feedback_list/ui/feedback_list_test.dart
══╡ EXCEPTION CAUGHT BY FLUTTER TEST FRAMEWORK ╞════════════════════════════════════════════════════
The following TestFailure object was thrown running a test:
Expected: exactly one matching node in the widget tree
Actual: _WidgetTypeFinder:<zero widgets with type "CircularProgressIndicator" (ignoring offstage
widgets)>
Which: means none were found but one was expected
When the exception was thrown, this was the stack:
#4 main.<anonymous closure>.<anonymous closure> (file:///Users/pankajsahdevea/Desktop/HD/Work/Haufe/Code/IF2.0/if_ui_Sep13,2019/test/widget_test/dashboard/feedback/feedback_list/ui/feedback_list_test.dart:45:7)
<asynchronous suspension>
#5 testWidgets.<anonymous closure>.<anonymous closure> (package:flutter_test/src/widget_tester.dart:124:25)
#6 TestWidgetsFlutterBinding._runTestBody (package:flutter_test/src/binding.dart:696:19)
<asynchronous suspension>
#9 TestWidgetsFlutterBinding._runTest (package:flutter_test/src/binding.dart:679:14)
#10 AutomatedTestWidgetsFlutterBinding.runTest.<anonymous closure> (package:flutter_test/src/binding.dart:1050:24)
#16 AutomatedTestWidgetsFlutterBinding.runTest (package:flutter_test/src/binding.dart:1047:15)
#17 testWidgets.<anonymous closure> (package:flutter_test/src/widget_tester.dart:121:22)
#18 Declarer.test.<anonymous closure>.<anonymous closure>.<anonymous closure> (package:test_api/src/backend/declarer.dart:171:27)
<asynchronous suspension>
#19 Invoker.waitForOutstandingCallbacks.<anonymous closure> (package:test_api/src/backend/invoker.dart:242:15)
#24 Invoker.waitForOutstandingCallbacks (package:test_api/src/backend/invoker.dart:239:5)
#25 Declarer.test.<anonymous closure>.<anonymous closure> (package:test_api/src/backend/declarer.dart:169:33)
#30 Declarer.test.<anonymous closure> (package:test_api/src/backend/declarer.dart:168:13)
#31 Invoker._onRun.<anonymous closure>.<anonymous closure>.<anonymous closure>.<anonymous closure> (package:test_api/src/backend/invoker.dart:392:25)
#45 _Timer._runTimers (dart:isolate-patch/timer_impl.dart:384:19)
#46 _Timer._handleMessage (dart:isolate-patch/timer_impl.dart:418:5)
#47 _RawReceivePortImpl._handleMessage (dart:isolate-patch/isolate_patch.dart:174:12)
(elided 28 frames from class _FakeAsync, package dart:async, package dart:async-patch, and package stack_trace)
This was caught by the test expectation on the following line:
file:///Users/pankajsahdevea/Desktop/HD/Work/Haufe/Code/IF2.0/if_ui_Sep13,2019/test/widget_test/dashboard/feedback/feedback_list/ui/feedback_list_test.dart line 45
The test description was:
validate Feedback List widget
════════════════════════════════════════════════════════════════════════════════════════════════════
Test failed. See exception logs above.
The test description was: validate Feedback List widget
Related
While working with Firebase Firestore, I am coming across the following error:
E/flutter ( 4477): [ERROR:flutter/shell/common/shell.cc(93)] Dart Unhandled Exception: type 'Future<Group>' is not a subtype of type 'Group', stack trace: #0 new List.from (dart:core-patch/array_patch.dart:41:5)
E/flutter ( 4477): #1 GroupService.getGroups (package:money_manager/core/services/group_service.dart:56:21)
E/flutter ( 4477): <asynchronous suspension>
E/flutter ( 4477): #2 GroupViewModel._getAllGroups (package:money_manager/core/view_models/group_viewmodel.dart:44:26)
E/flutter ( 4477): <asynchronous suspension>
E/flutter ( 4477):
Though I think I have made proper use of async-await wherever necessary, I am not being able to figure out this error. Relevant code:
in group-service.dart :
Future<List<Group>> getGroups() async {
final userData = await getUserData();
List<Group> groups = [];
if (userData['groups'] != null) {
List<String> groupIds = List.from(userData['groups'].map((e) => e['id']));
groups = List.from(groupIds.map((e) async {
return await getGroupFromId(e);
}));
}
return groups;
}
Future<Group> getGroupFromId(String groupId) async {
final groupData = await getGroupData(groupId);
return Group.fromJson(groupData);
}
Future<Map<String, dynamic>> getGroupData(String groupId) async {
DocumentReference groupDoc =
FirebaseFirestore.instance.collection('groups').doc(groupId);
final snapshot = await groupDoc.get();
Map<String, dynamic> groupData = snapshot.data() as Map<String, dynamic>;
return groupData;
}
in group_viewmodel.dart:
List<Group> _userGroups = [];
void _getAllGroups() async {
List<Group> groups = await _groupService.getGroups();
_userGroups = groups;
}
The problem is in the following line:
groups = List.from(groupIds.map((e) async {
return await getGroupFromId(e);
}));
Even though you're using await before the return of the map() function, it will still return a Future. map() is a synchronous function, and it doesn't run the inner function asynchronously. Thus, it will return an Iterable<Future<Group>>, which fails to be converted into a List<Group> in the List.from() function.
There is a handy function that takes an iterable of futures and waits for each one of them, Future.wait(). Here's how your code will look like with it:
groups = List.from(await Future.wait(groupIds.map((e) async {
return await getGroupFromId(e);
})));
And even better with tear-offs:
groups = List.from(await Future.wait(groupIds.map(getGroupFromId)));
There is an example in asio, which caches the sent messages in a deque. I think when there are too many unsent messages in this deque, such as 1000, I want to process it through constbuffersequence, that is, batch sending, so the following How should the code be changed, thank you!
void deliver(const chat_message& msg)
{
bool write_in_progress = !write_msgs_.empty();
write_msgs_.push_back(msg);
if (!write_in_progress)
{
boost::asio::async_write(socket_,
boost::asio::buffer(write_msgs_.front().data(),
write_msgs_.front().length()),
boost::bind(&chat_session::handle_write, shared_from_this(),
boost::asio::placeholders::error));
}
}
void handle_write(const boost::system::error_code& error)
{
if (!error)
{
write_msgs_.pop_front();
if (!write_msgs_.empty())
{
boost::asio::async_write(socket_,
boost::asio::buffer(write_msgs_.front().data(),
write_msgs_.front().length()),
boost::bind(&chat_session::handle_write, shared_from_this(),
boost::asio::placeholders::error));
}
}
else
{
room_.leave(shared_from_this());
}
}
You can transform the deque to any container modeling the const buffer sequence concept:
std::vector<asio::const_buffer> buffers;
std::transform(
begin(write_msgs_), end(write_msgs_), back_inserter(buffers),
[](Message const& s) { return asio::buffer(s); });
async_write( //
socket_, buffers,
[this, self = shared_from_this()] //
(error_code ec, std::size_t bytes_written) {
// ...
write_msgs_.clear();
});
The transform is a force of habit here, you might prefer
std::vector<asio::const_buffer> buffers;
for (auto& s: write_msgs_)
buffers.push_back(asio::buffer(s));
Live Demo
Modified from this recent example How to safely write to a socket from multiple threads?:
Live On Coliru
#include <boost/asio.hpp>
#include <deque>
#include <iostream>
namespace asio = boost::asio;
using boost::system::error_code;
using asio::ip::tcp;
using Message = std::string;
class chat_session : public std::enable_shared_from_this<chat_session> {
public:
chat_session(tcp::socket socket) : socket_(std::move(socket)) {}
void start() { do_read(); }
void deliver_many(std::vector<Message> msgs) {
post(socket_.get_executor(),
[this, msgs = std::move(msgs), self = shared_from_this()] //
() mutable {
for (auto& msg : msgs) {
do_write(std::move(msg));
}
});
}
void deliver(Message msg) {
post(socket_.get_executor(),
[this, msg = std::move(msg), self = shared_from_this()] //
() mutable { do_write(std::move(msg)); });
}
private:
void do_read() {
async_read_until(
socket_, asio::dynamic_buffer(incoming_), '\0',
[this, self = shared_from_this()] //
(error_code ec, std::size_t length) {
if (!ec) {
process_message(incoming_.substr(0, length - 1));
incoming_.erase(0, length);
do_read();
} else if (ec != asio::error::eof) {
std::cerr << "Read error: " << ec.message() << std::endl;
}
});
}
void do_write(Message message)
{
write_msgs_.push_back(std::move(message)); // assumed on (implicit) strand
if (write_msgs_.size() == 1) {
write_loop();
}
}
void write_loop() {
std::cerr << "write_loop with write_msgs_.size() = " << write_msgs_.size() << std::endl;
if (write_msgs_.empty())
return;
if (write_msgs_.size() > 100) {
std::vector<asio::const_buffer> buffers;
std::transform(
begin(write_msgs_), end(write_msgs_), back_inserter(buffers),
[](Message const& s) { return asio::buffer(s); });
async_write( //
socket_, buffers,
[this, self = shared_from_this()] //
(error_code ec, std::size_t /*length*/) {
if (!ec) {
write_msgs_.clear();
write_loop();
} else if (ec != asio::error::eof) {
std::cerr << "Write error: " << ec.message() << std::endl;
}
});
} else {
async_write( //
socket_, asio::buffer(write_msgs_.front()),
[this, self = shared_from_this()] //
(error_code ec, std::size_t /*length*/) {
if (!ec) {
write_msgs_.pop_front();
write_loop();
} else if (ec != asio::error::eof) {
std::cerr << "Write error: " << ec.message() << std::endl;
}
});
}
}
void process_message(Message const& message) {
std::vector<Message> responses;
for (int i = 0; i < 200; ++i) {
responses.push_back("Response #" + std::to_string(i) + " for " +
message + "\n");
}
// dispatch/post to executor because we might be on a different thread (not in this example)
// (not in this example)
post(socket_.get_executor(),
std::bind(&chat_session::deliver_many, shared_from_this(),
std::move(responses)));
}
tcp::socket socket_;
Message incoming_;
std::deque<Message> write_msgs_;
};
class server {
public:
server(asio::any_io_executor ex, unsigned short port)
: acceptor_(ex, tcp::endpoint(tcp::v4(), port))
{
do_accept();
}
private:
void do_accept()
{
acceptor_.async_accept(
make_strand(acceptor_.get_executor()),
[this](error_code ec, tcp::socket&& s) {
if (!ec) {
std::cout << "Accepted " << s.remote_endpoint() << std::endl;
std::make_shared<chat_session>(std::move(s))->start();
}
do_accept();
});
}
tcp::acceptor acceptor_;
};
int main() {
asio::thread_pool ctx;
server s(ctx.get_executor(), 8989);
ctx.join();
}
When sending a single message from a client:
g++ -std=c++20 -O2 -Wall -pedantic -pthread main.cpp
./a.out&
sleep .5; printf 'HelloWorld\0' | nc 127.0.0.1 8989 -w1
shows e.g.:
Accepted 127.0.0.1:39538
write_loop with write_msgs_.size() = 1
Response #0 for HelloWorld
write_loop with write_msgs_.size() = 199
Response #1 for HelloWorld
Response #2 for HelloWorld
Response #3 for HelloWorld
Response #4 for HelloWorld
Response #5 for HelloWorld
Response #6 for HelloWorld
Response #7 for HelloWorld
Response #8 for HelloWorld
Response #9 for HelloWorld
Response #10 for HelloWorld
Response #11 for HelloWorld
Response #12 for HelloWorld
Response #13 for HelloWorld
Response #14 for HelloWorld
Response #15 for HelloWorld
Response #16 for HelloWorld
Response #17 for HelloWorld
Response #18 for HelloWorld
Response #19 for HelloWorld
Response #20 for HelloWorld
Response #21 for HelloWorld
Response #22 for HelloWorld
Response #23 for HelloWorld
Response #24 for HelloWorld
Response #25 for HelloWorld
Response #26 for HelloWorld
Response #27 for HelloWorld
Response #28 for HelloWorld
Response #29 for HelloWorld
Response #30 for HelloWorld
Response #31 for HelloWorld
Response #32 for HelloWorld
Response #33 for HelloWorld
Response #34 for HelloWorld
Response #35 for HelloWorld
Response #36 for HelloWorld
Response #37 for HelloWorld
Response #38 for HelloWorld
Response #39 for HelloWorld
Response #40 for HelloWorld
Response #41 for HelloWorld
Response #42 for HelloWorld
Response #43 for HelloWorld
Response #44 for HelloWorld
Response #45 for HelloWorld
Response #46 for HelloWorld
Response #47 for HelloWorld
Response #48 for HelloWorld
Response #49 for HelloWorld
Response #50 for HelloWorld
Response #51 for HelloWorld
Response #52 for HelloWorld
Response #53 for HelloWorld
Response #54 for HelloWorld
Response #55 for HelloWorld
Response #56 for HelloWorld
Response #57 for HelloWorld
Response #58 for HelloWorld
Response #59 for HelloWorld
Response #60 for HelloWorld
Response #61 for HelloWorld
Response #62 for HelloWorld
Response #63 for HelloWorld
Response #64 for HelloWorld
Response #65 for HelloWorld
Response #66 for HelloWorld
Response #67 for HelloWorld
Response #68 for HelloWorld
Response #69 for HelloWorld
Response #70 for HelloWorld
Response #71 for HelloWorld
Response #72 for HelloWorld
Response #73 for HelloWorld
Response #74 for HelloWorld
Response #75 for HelloWorld
Response #76 for HelloWorld
Response #77 for HelloWorld
Response #78 for HelloWorld
Response #79 for HelloWorld
Response #80 for HelloWorld
Response #81 for HelloWorld
Response #82 for HelloWorld
Response #83 for HelloWorld
Response #84 for HelloWorld
Response #85 for HelloWorld
Response #86 for HelloWorld
Response #87 for HelloWorld
Response #88 for HelloWorld
Response #89 for HelloWorld
Response #90 for HelloWorld
Response #91 for HelloWorld
Response #92 for HelloWorld
Response #93 for HelloWorld
Response #94 for HelloWorld
Response #95 for HelloWorld
Response #96 for HelloWorld
Response #97 for HelloWorld
Response #98 for HelloWorld
Response #99 for HelloWorld
Response #100 for HelloWorld
Response #101 for HelloWorld
Response #102 for HelloWorld
Response #103 for HelloWorld
Response #104 for HelloWorld
Response #105 for HelloWorld
Response #106 for HelloWorld
Response #107 for HelloWorld
Response #108 for HelloWorld
Response #109 for HelloWorld
Response #110 for HelloWorld
Response #111 for HelloWorld
Response #112 for HelloWorld
Response #113 for HelloWorld
Response #114 for HelloWorld
Response #115 for HelloWorld
Response #116 for HelloWorld
Response #117 for HelloWorld
Response #118 for HelloWorld
Response #119 for HelloWorld
Response #120 for HelloWorld
Response #121 for HelloWorld
Response #122 for HelloWorld
Response #123 for HelloWorld
Response #124 for HelloWorld
Response #125 for HelloWorld
Response #126 for HelloWorld
Response #127 for HelloWorld
Response #128 for HelloWorld
Response #129 for HelloWorld
Response #130 for HelloWorld
Response #131 for HelloWorld
Response #132 for HelloWorld
Response #133 for HelloWorld
Response #134 for HelloWorld
Response #135 for HelloWorld
Response #136 for HelloWorld
Response #137 for HelloWorld
Response #138 for HelloWorld
Response #139 for HelloWorld
Response #140 for HelloWorld
Response #141 for HelloWorld
Response #142 for HelloWorld
Response #143 for HelloWorld
Response #144 for HelloWorld
Response #145 for HelloWorld
Response #146 for HelloWorld
Response #147 for HelloWorld
Response #148 for HelloWorld
Response #149 for HelloWorld
Response #150 for HelloWorld
Response #151 for HelloWorld
Response #152 for HelloWorld
Response #153 for HelloWorld
Response #154 for HelloWorld
Response #155 for HelloWorld
Response #156 for HelloWorld
Response #157 for HelloWorld
Response #158 for HelloWorld
Response #159 for HelloWorld
Response #160 for HelloWorld
Response #161 for HelloWorld
Response #162 for HelloWorld
Response #163 for HelloWorld
Response #164 for HelloWorld
Response #165 for HelloWorld
Response #166 for HelloWorld
Response #167 for HelloWorld
Response #168 for HelloWorld
Response #169 for HelloWorld
Response #170 for HelloWorld
Response #171 for HelloWorld
Response #172 for HelloWorld
Response #173 for HelloWorld
Response #174 for HelloWorld
Response #175 for HelloWorld
Response #176 for HelloWorld
Response #177 for HelloWorld
Response #178 for HelloWorld
Response #179 for HelloWorld
Response #180 for HelloWorld
Response #181 for HelloWorld
Response #182 for HelloWorld
Response #183 for HelloWorld
Response #184 for HelloWorld
Response #185 for HelloWorld
Response #186 for HelloWorld
Response #187 for HelloWorld
Response #188 for HelloWorld
Response #189 for HelloWorld
Response #190 for HelloWorld
Response #191 for HelloWorld
Response #192 for HelloWorld
Response #193 for HelloWorld
Response #194 for HelloWorld
Response #195 for HelloWorld
Response #196 for HelloWorld
Response #197 for HelloWorld
Response #198 for HelloWorld
Response #199 for HelloWorld
write_loop with write_msgs_.size() = 0
I have the following output in one of my tests:
Assertion failed:
Expected :[[] [] [] [] [] [] [] [] [] [] [] [] [] [] [] [] [] [] [] [] [] [] [] [] [] [] ["seq07"] [] [] [] [] [] [] [] [] [] [] [] [] [] [] [] [] [] [] [] [] [] [] [] [] [] [] [] [] [] [] [] [] [] [] [] [] [] [] []]
Actual :[() () () () () () () () () () () () () () () () () () () () () () () () () () ("seq07") () () () () () () () () () () () () () () () () () () () () () () () () () () () () () () () () ()]
What do () and ("seq07") mean in this output?
As noted in another answer, () is an empty list and [] is an empty vector.
Note however that = compares the contents of lists and vectors, it ignores the type of the container:
(= '("seq07") ["seq07"]) ;; => true
(= '(()) [[]]) ;; => true
The assertion failure in the question is due to the actual vector having fewer elements than the expected vector:
(= ['("seq07")] ['("seq07") '()]) ;; => false
() is a notation for list whereas [] is a notation for vectors
() is an empty list and ("seq07") is a list that contains a single member - the string seq07
you can read more about clojure lists here
EDIT: just found this interesting SO question about lists vs vectors
In web programming, a common pattern for form submission is:
If the form is valid, redirect to another page (Post/Redirect/Get).
If the form is not valid, redisplay the form (possibly including error messages this time).
How do I express this in Ocsigen?
I've been reading the documentation, but could not figure out how to accomplish this simple (and very common) task.
Example use case:
Suppose I have a login form that guards against unauthorized access to the admin panel (a page that should only be accessed by administrators). If the user provides the correct credentials at the login form, the user should be redirected to the admin panel. If the credentials are incorrect, the user should be redirected back to the login form. So far, I have successfully implemented this functionality.
However, I am at loss when it comes to implementing the following: if the user is already logged in and tries to access the login form, the user should be redirected to the admin panel. Also, if the user is not logged in and tries to access the admin panel, the user should be redirected to the login form.
Below is my code up the point I got stuck:
(* Secret login credentials. *)
let username = "admin"
let password = "123456"
(* Create Eliom services. *)
let login_form_service = Eliom_service.create
~path:(Eliom_service.Path ["login"])
~meth:(Eliom_service.Get Eliom_parameter.unit)
()
let login_service = Eliom_service.create_attached_post
~fallback:login_form_service
~post_params:Eliom_parameter.(string "user" ** string "pass")
()
let admin_panel_service = Eliom_service.create
~path:(Eliom_service.Path ["admin-panel"])
~meth:(Eliom_service.Get Eliom_parameter.unit)
()
let session_username : string option Eliom_reference.eref =
Eliom_reference.eref ~scope:Eliom_common.default_session_scope None
(* Register Eliom services. *)
let () = Eliom_content.Html.D.(
Eliom_registration.Html.register
~service:login_form_service
(fun () () -> Lwt.return
(Eliom_tools.D.html
~title:"Login"
(body [h1 [pcdata "Login"];
Form.post_form
~service:login_service
(fun (user, pass) ->
[fieldset
[label [pcdata "Username: "];
Form.input ~input_type:`Text
~name:user
Form.string;
br ();
label [pcdata "Password: "];
Form.input ~input_type:`Password
~name:pass
Form.string;
br ();
Form.input ~input_type:`Submit
~value:"Login"
Form.string
]]) ()])));
Eliom_registration.Redirection.register
~service:login_service
(fun () (user, pass) ->
if user = username && pass = password then (
Eliom_reference.set session_username (Some username);
Lwt.return (Eliom_registration.Redirection admin_panel_service))
else
Lwt.return (Eliom_registration.Redirection login_form_service));
Eliom_registration.Html.register
~service:admin_panel_service
(fun () () ->
(* Admin panel html here ... *))
);
What is the proper method of solving this problem?
Thank you.
I don't know if you found the solution as your question is kind of old by now but here is what I found:
I used "Registering services that decide what they want to send" from https://ocsigen.org/eliom/6.3/manual/server-outputs#redirections
The idea is to register you services with Eliom_registration.Any, this allows the handler attached to the service to decide on the fly the type of answer to provide by using the appropriate send function.
(* Secret login credentials. *)
let username = "admin"
let password = "123456"
(* Create Eliom services. *)
let login_form_service = Eliom_service.create
~path:(Eliom_service.Path ["login"])
~meth:(Eliom_service.Get Eliom_parameter.unit)
()
let login_service = Eliom_service.create_attached_post
~fallback:login_form_service
~post_params:Eliom_parameter.(string "user" ** string "pass")
()
let admin_panel_service = Eliom_service.create
~path:(Eliom_service.Path ["admin-panel"])
~meth:(Eliom_service.Get Eliom_parameter.unit)
()
let session_username : string option Eliom_reference.eref =
Eliom_reference.eref ~scope:Eliom_common.default_session_scope None
let login_panel () = Eliom_content.Html.D.(
Eliom_tools.D.html
~title:"Login"
(body [
h1 [pcdata "Login"];
Form.post_form
~service:login_service
(fun (user, pass) ->
[fieldset
[label [pcdata "Username: "];
Form.input ~input_type:`Text
~name:user
Form.string;
br ();
label [pcdata "Password: "];
Form.input ~input_type:`Password
~name:pass
Form.string;
br ();
Form.input ~input_type:`Submit
~value:"Login"
Form.string
]]) ()])
)
let admin_panel () = Eliom_content.Html.F.(
Eliom_tools.F.html
~title:"Fake Admin Panel"
(body [h1 [pcdata "Fake Admin Panel"];])
)
(* Some helper functions *)
let admin_credentials ~user_is_admin ~user_is_not_admin =
let%lwt usr = Eliom_reference.get session_username in
if usr = Some username then user_is_admin ()
else user_is_not_admin ()
let send_redirection service =
Eliom_registration.Redirection.send (Eliom_registration.Redirection service)
let send_page page =
Eliom_registration.Html.send page
(* Register Eliom services. *)
let () = Eliom_content.Html.D.(
Eliom_registration.Any.register
~service:login_form_service
(fun () () ->
admin_credentials
~user_is_admin:(fun () -> send_redirection admin_panel_service)
~user_is_not_admin:(fun () -> send_page (login_panel ()))
);
Eliom_registration.Redirection.register
~service:login_service
(fun () (user, pass) ->
if user = username && pass = password then (
let%lwt _ = Eliom_reference.set session_username (Some username) in
Lwt.return (Eliom_registration.Redirection admin_panel_service))
else
Lwt.return (Eliom_registration.Redirection login_form_service));
Eliom_registration.Any.register
~service:admin_panel_service
(fun () () ->
admin_credentials
~user_is_admin:(fun () -> send_page (admin_panel ()))
~user_is_not_admin:(fun () -> send_redirection login_form_service))
)
I have a problem and I don't know why is it occurs.
My Qt project includes class AllExceptions. It has the following constructor:
AllExceptions::AllExceptions(std::string errName){
errorMessage = errName;
} //<<<---
I call constructor in the following way:
throw AllExceptions(response);
where response is a string that represents smtp server answer.
Problem: program stucks at constructing object. I debbuged and figured out that it stucks at point that I marked <<<---.
Any advice, please.
EDIT: stack at that point
AllExceptions::AllExceptions (this=0xaf47d0, errName={static npos = <optimized out>, _M_dataplus = {<std::allocator<char>> = {<__gnu_cxx::new_allocator<char>> = {<No data fields>}, <No data fields>}, _M_p = 0x7fffffffca10 \"\\330;\\257\"}})
Email::sendMessage (this=0xa2e950)
NewMailWindow::sendMail (this=0x885bb0)
NewMailWindow::qt_static_metacall (_o=0x885bb0, _c=QMetaObject::InvokeMetaMethod, _id=0, _a=0x7fffffffcdb0)
QMetaObject::activate(QObject*, QMetaObject const*, int, void**) ()
QAbstractButton::clicked(bool) ()
?? ()
?? ()
QAbstractButton::mouseReleaseEvent(QMouseEvent*) ()
QWidget::event(QEvent*) ()
QApplicationPrivate::notify_helper(QObject*, QEvent*) ()
QApplication::notify(QObject*, QEvent*) ()
QCoreApplication::notifyInternal(QObject*, QEvent*) ()
QApplicationPrivate::sendMouseEvent(QWidget*, QMouseEvent*, QWidget*, QWidget*, QWidget**, QPointer<QWidget>&, bool) ()
?? ()
QApplication::x11ProcessEvent(_XEvent*) ()
?? ()
g_main_context_dispatch ()
?? ()
g_main_context_iteration ()
QEventDispatcherGlib::processEvents(QFlags<QEventLoop::ProcessEventsFlag>) ()
?? ()
QEventLoop::processEvents(QFlags<QEventLoop::ProcessEventsFlag>) ()
QEventLoop::exec(QFlags<QEventLoop::ProcessEventsFlag>) ()
QCoreApplication::exec() ()
main (argc=1, argv=0x7fffffffe478)
Header file:
class AllExceptions{
public:
AllExceptions(std::string errName);
std::string getErrMess() {return errorMessage;};
void displayError();
private:
std::string errorMessage;
};