Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
A
Actor Framework
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Operations
Operations
Metrics
Environments
Analytics
Analytics
CI / CD
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
cpp-libs
Actor Framework
Commits
b423b86d
Commit
b423b86d
authored
Dec 16, 2016
by
Dominik Charousset
Committed by
Marian Triebe
Apr 23, 2017
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Improve testing DSL
parent
9a74609e
Changes
7
Show whitespace changes
Inline
Side-by-side
Showing
7 changed files
with
264 additions
and
51 deletions
+264
-51
libcaf_core/caf/scheduler/test_coordinator.hpp
libcaf_core/caf/scheduler/test_coordinator.hpp
+2
-1
libcaf_core/caf/type_erased_tuple.hpp
libcaf_core/caf/type_erased_tuple.hpp
+26
-0
libcaf_core/src/test_coordinator.cpp
libcaf_core/src/test_coordinator.cpp
+4
-2
libcaf_core/test/actor_termination.cpp
libcaf_core/test/actor_termination.cpp
+36
-16
libcaf_core/test/composition.cpp
libcaf_core/test/composition.cpp
+31
-8
libcaf_core/test/type_erased_tuple.cpp
libcaf_core/test/type_erased_tuple.cpp
+39
-0
libcaf_test/caf/test/dsl.hpp
libcaf_test/caf/test/dsl.hpp
+126
-24
No files found.
libcaf_core/caf/scheduler/test_coordinator.hpp
View file @
b423b86d
...
...
@@ -24,6 +24,7 @@
#include <deque>
#include <chrono>
#include <limits>
#include <cstddef>
#include <algorithm>
...
...
@@ -105,7 +106,7 @@ public:
/// Executes events until the job queue is empty and no pending timeouts are
/// left. Returns the number of processed events.
size_t
run
();
size_t
run
(
size_t
max_count
=
std
::
numeric_limits
<
size_t
>::
max
()
);
/// Tries to dispatch a single delayed message.
bool
dispatch_once
();
...
...
libcaf_core/caf/type_erased_tuple.hpp
View file @
b423b86d
...
...
@@ -124,6 +124,32 @@ public:
return
*
reinterpret_cast
<
const
T
*>
(
get
(
pos
));
}
template
<
class
T
,
size_t
Pos
>
struct
typed_index
{};
template
<
class
T
,
size_t
Pos
>
static
constexpr
typed_index
<
T
,
Pos
>
make_typed_index
()
{
return
{};
}
template
<
class
T
,
size_t
Pos
>
const
T
&
get_as
(
typed_index
<
T
,
Pos
>
)
const
{
return
*
reinterpret_cast
<
const
T
*>
(
get
(
Pos
));
}
template
<
class
...
Ts
,
long
...
Is
>
std
::
tuple
<
const
Ts
&
...
>
get_as_tuple
(
detail
::
type_list
<
Ts
...
>
,
detail
::
int_list
<
Is
...
>
)
const
{
return
std
::
tuple
<
const
Ts
&
...
>
{
get_as
<
Ts
>
(
Is
)...};
//return get_as<Ts>(Is)...;//(make_typed_index<Ts, Is>())...;
}
template
<
class
...
Ts
>
std
::
tuple
<
const
Ts
&
...
>
get_as_tuple
()
const
{
return
get_as_tuple
(
detail
::
type_list
<
Ts
...
>
{},
typename
detail
::
il_range
<
0
,
sizeof
...(
Ts
)
>::
type
{});
}
/// Convenience function for `*reinterpret_cast<T*>(get_mutable())`.
template
<
class
T
>
T
&
get_mutable_as
(
size_t
pos
)
{
...
...
libcaf_core/src/test_coordinator.cpp
View file @
b423b86d
...
...
@@ -19,6 +19,8 @@
#include "caf/scheduler/test_coordinator.hpp"
#include <limits>
#include "caf/resumable.hpp"
#include "caf/monitorable_actor.hpp"
...
...
@@ -131,9 +133,9 @@ bool test_coordinator::run_once() {
return
true
;
}
size_t
test_coordinator
::
run
()
{
size_t
test_coordinator
::
run
(
size_t
max_count
)
{
size_t
res
=
0
;
while
(
run_once
())
while
(
r
es
<
max_count
&&
r
un_once
())
++
res
;
return
res
;
}
...
...
libcaf_core/test/actor_termination.cpp
View file @
b423b86d
...
...
@@ -21,9 +21,7 @@
// this suite tests whether actors terminate as expect in several use cases
#define CAF_SUITE actor_termination
#include "caf/test/unit_test.hpp"
#include "caf/all.hpp"
#include "caf/test/dsl.hpp"
using
namespace
caf
;
...
...
@@ -36,27 +34,23 @@ behavior mirror_impl(event_based_actor* self) {
};
}
struct
fixture
{
actor_system_config
cfg
;
actor_system
system
;
scoped_actor
scoped_self
;
struct
fixture
:
test_coordinator_fixture
<>
{
actor
mirror
;
actor
testee
;
fixture
()
:
system
(
cfg
),
scoped_self
(
system
),
mirror
(
system
.
spawn
(
mirror_impl
))
{
// nop
fixture
()
{
mirror
=
sys
.
spawn
(
mirror_impl
);
// run initialization code or mirror
sched
.
run_once
();
}
template
<
class
...
Ts
>
void
spawn
(
Ts
&&
...
xs
)
{
testee
=
s
coped_s
elf
->
spawn
(
std
::
forward
<
Ts
>
(
xs
)...);
testee
=
self
->
spawn
(
std
::
forward
<
Ts
>
(
xs
)...);
}
~
fixture
()
{
s
coped_s
elf
->
wait_for
(
testee
);
self
->
wait_for
(
testee
);
}
};
...
...
@@ -73,6 +67,10 @@ CAF_TEST(single_multiplexed_request) {
);
};
spawn
(
f
,
mirror
);
// run initialization code of testee
sched
.
run_once
();
expect
((
int
),
from
(
testee
).
to
(
mirror
).
with
(
42
));
expect
((
int
),
from
(
mirror
).
to
(
testee
).
with
(
42
));
}
CAF_TEST
(
multiple_multiplexed_requests
)
{
...
...
@@ -85,6 +83,14 @@ CAF_TEST(multiple_multiplexed_requests) {
);
};
spawn
(
f
,
mirror
);
// run initialization code of testee
sched
.
run_once
();
expect
((
int
),
from
(
testee
).
to
(
mirror
).
with
(
42
));
expect
((
int
),
from
(
testee
).
to
(
mirror
).
with
(
42
));
expect
((
int
),
from
(
testee
).
to
(
mirror
).
with
(
42
));
expect
((
int
),
from
(
mirror
).
to
(
testee
).
with
(
42
));
expect
((
int
),
from
(
mirror
).
to
(
testee
).
with
(
42
));
expect
((
int
),
from
(
mirror
).
to
(
testee
).
with
(
42
));
}
CAF_TEST
(
single_awaited_request
)
{
...
...
@@ -96,19 +102,33 @@ CAF_TEST(single_awaited_request) {
);
};
spawn
(
f
,
mirror
);
// run initialization code of testee
sched
.
run_once
();
expect
((
int
),
from
(
testee
).
to
(
mirror
).
with
(
42
));
expect
((
int
),
from
(
mirror
).
to
(
testee
).
with
(
42
));
}
CAF_TEST
(
multiple_awaited_requests
)
{
auto
f
=
[
&
](
event_based_actor
*
self
,
actor
server
)
{
for
(
int
i
=
0
;
i
<
3
;
++
i
)
self
->
request
(
server
,
infinite
,
42
).
await
(
self
->
request
(
server
,
infinite
,
i
).
await
(
[
=
](
int
x
)
{
CAF_MESSAGE
(
"received response #"
<<
(
i
+
1
));
CAF_REQUIRE_EQUAL
(
x
,
42
);
CAF_REQUIRE_EQUAL
(
x
,
i
);
}
);
};
spawn
(
f
,
mirror
);
// run initialization code of testee
sched
.
run_once
();
self
->
monitor
(
testee
);
expect
((
int
),
from
(
testee
).
to
(
mirror
).
with
(
0
));
expect
((
int
),
from
(
testee
).
to
(
mirror
).
with
(
1
));
expect
((
int
),
from
(
testee
).
to
(
mirror
).
with
(
2
));
// request().await() processes messages out-of-order,
// which means we cannot check using expect()
sched
.
run
();
expect
((
down_msg
),
from
(
testee
).
to
(
self
).
with
(
_
));
}
CAF_TEST_FIXTURE_SCOPE_END
()
libcaf_core/test/composition.cpp
View file @
b423b86d
...
...
@@ -29,6 +29,9 @@ behavior multiplier(int x) {
return
{
[
=
](
int
y
)
{
return
x
*
y
;
},
[
=
](
int
y1
,
int
y2
)
{
return
x
*
y1
*
y2
;
}
};
}
...
...
@@ -37,6 +40,17 @@ behavior adder(int x) {
return
{
[
=
](
int
y
)
{
return
x
+
y
;
},
[
=
](
int
y1
,
int
y2
)
{
return
x
+
y1
+
y2
;
}
};
}
behavior
float_adder
(
float
x
)
{
return
{
[
=
](
float
y
)
{
return
x
+
y
;
}
};
}
...
...
@@ -52,9 +66,9 @@ CAF_TEST(depth2) {
auto
stage2
=
sys
.
spawn
(
adder
,
10
);
auto
testee
=
stage2
*
stage1
;
self
->
send
(
testee
,
1
);
expect
(
int
,
from
(
self
).
to
(
stage1
).
with
(
1
));
expect
(
int
,
from
(
self
).
to
(
stage2
).
with
(
4
));
CAF_CHECK_EQUAL
(
fetch_result
<
int
>
(),
14
);
expect
(
(
int
)
,
from
(
self
).
to
(
stage1
).
with
(
1
));
expect
(
(
int
)
,
from
(
self
).
to
(
stage2
).
with
(
4
));
expect
((
int
),
from
(
stage2
).
to
(
self
).
with
(
14
)
);
}
CAF_TEST
(
depth3
)
{
...
...
@@ -62,11 +76,20 @@ CAF_TEST(depth3) {
auto
stage2
=
sys
.
spawn
(
adder
,
10
);
auto
testee
=
stage1
*
stage2
*
stage1
;
self
->
send
(
testee
,
1
);
expect
(
int
,
from
(
self
).
to
(
stage1
).
with
(
1
));
expect
(
int
,
from
(
self
).
to
(
stage2
).
with
(
4
));
expect
(
int
,
from
(
self
).
to
(
stage1
).
with
(
14
));
CAF_CHECK_EQUAL
(
fetch_result
<
int
>
(),
56
);
expect
(
(
int
)
,
from
(
self
).
to
(
stage1
).
with
(
1
));
expect
(
(
int
)
,
from
(
self
).
to
(
stage2
).
with
(
4
));
expect
(
(
int
)
,
from
(
self
).
to
(
stage1
).
with
(
14
));
expect
((
int
),
from
(
stage1
).
to
(
self
).
with
(
56
)
);
}
CAF_TEST_FIXTURE_SCOPE_END
()
CAF_TEST
(
depth2_type_mismatch
)
{
auto
stage1
=
sys
.
spawn
(
multiplier
,
4
);
auto
stage2
=
sys
.
spawn
(
float_adder
,
10
);
auto
testee
=
stage2
*
stage1
;
self
->
send
(
testee
,
1
);
expect
((
int
),
from
(
self
).
to
(
stage1
).
with
(
1
));
expect
((
int
),
from
(
self
).
to
(
stage2
).
with
(
4
));
expect
((
error
),
from
(
stage2
).
to
(
self
).
with
(
sec
::
unexpected_message
));
}
CAF_TEST_FIXTURE_SCOPE_END
()
libcaf_core/test/type_erased_tuple.cpp
0 → 100644
View file @
b423b86d
/******************************************************************************
* ____ _ _____ *
* / ___| / \ | ___| C++ *
* | | / _ \ | |_ Actor *
* | |___ / ___ \| _| Framework *
* \____/_/ \_|_| *
* *
* Copyright (C) 2011 - 2016 *
* Dominik Charousset <dominik.charousset (at) haw-hamburg.de> *
* *
* Distributed under the terms and conditions of the BSD 3-Clause License or *
* (at your option) under the terms and conditions of the Boost Software *
* License 1.0. See accompanying files LICENSE and LICENSE_ALTERNATIVE. *
* *
* If you did not receive a copy of the license files, see *
* http://opensource.org/licenses/BSD-3-Clause and *
* http://www.boost.org/LICENSE_1_0.txt. *
******************************************************************************/
#include "caf/config.hpp"
#define CAF_SUITE type_erased_tuple
#include "caf/test/unit_test.hpp"
#include "caf/all.hpp"
#include "caf/make_type_erased_tuple_view.hpp"
using
namespace
std
;
using
namespace
caf
;
CAF_TEST
(
get_as_tuple
)
{
int
x
=
1
;
int
y
=
2
;
int
z
=
3
;
auto
tup
=
make_type_erased_tuple_view
(
x
,
y
,
z
);
auto
xs
=
tup
.
get_as_tuple
<
int
,
int
,
int
>
();
CAF_CHECK_EQUAL
(
xs
,
std
::
make_tuple
(
1
,
2
,
3
));
}
libcaf_test/caf/test/dsl.hpp
View file @
b423b86d
...
...
@@ -109,57 +109,156 @@ private:
};
template
<
class
T
>
class
expect_clause
{
struct
match_helper
{
T
&
ref
;
template
<
class
...
Fs
>
void
operator
()(
Fs
...
fs
)
{
struct
impl
:
Fs
...
{
using
result_type
=
void
;
impl
(
Fs
...
xs
)
:
Fs
(
xs
)...
{
// nop
}
};
impl
visitor
{
std
::
move
(
fs
)...};
apply_visitor
(
ref
,
visitor
);
}
};
template
<
class
T
>
match_helper
<
T
>
match
(
T
&
x
)
{
return
{
x
};
}
template
<
class
Derived
>
class
expect_clause_base
{
public:
expect_clause
(
caf
::
scheduler
::
test_coordinator
&
sched
)
:
sched_
(
sched
)
{
expect_clause_base
(
caf
::
scheduler
::
test_coordinator
&
sched
)
:
sched_
(
sched
),
mock_dest_
(
false
)
{
// nop
}
expect_clause
(
expect_clau
se
&&
other
)
expect_clause
_base
(
expect_clause_ba
se
&&
other
)
:
sched_
(
other
.
sched_
),
src_
(
std
::
move
(
other
.
src_
))
{
// nop
}
Derived
&
from
(
const
wildcard
&
)
{
return
dref
();
}
template
<
class
Handle
>
expect_clause
&
from
(
const
Handle
&
whom
)
{
Derived
&
from
(
const
Handle
&
whom
)
{
src_
=
caf
::
actor_cast
<
caf
::
strong_actor_ptr
>
(
whom
);
return
*
this
;
return
dref
()
;
}
template
<
class
Handle
>
expect_clause
&
to
(
const
Handle
&
whom
)
{
Derived
&
to
(
const
Handle
&
whom
)
{
CAF_REQUIRE
(
sched_
.
prioritize
(
whom
));
auto
ptr
=
sched_
.
next_job
<
caf
::
scheduled_actor
>
().
mailbox
().
peek
();
dest_
=
&
sched_
.
next_job
<
caf
::
scheduled_actor
>
();
auto
ptr
=
dest_
->
mailbox
().
peek
();
CAF_REQUIRE
(
ptr
!=
nullptr
);
if
(
src_
)
CAF_REQUIRE_EQUAL
(
ptr
->
sender
,
src_
);
return
*
this
;
return
dref
();
}
Derived
&
to
(
const
wildcard
&
whom
)
{
CAF_REQUIRE
(
sched_
.
prioritize
(
whom
));
dest_
=
&
sched_
.
next_job
<
caf
::
scheduled_actor
>
();
return
dref
();
}
Derived
&
to
(
const
caf
::
scoped_actor
&
whom
)
{
mock_dest_
=
true
;
dest_
=
whom
.
ptr
();
return
dref
();
}
template
<
class
...
Ts
>
void
with
(
Ts
&&
...
xs
)
{
std
::
integral_constant
<
bool
,
has_outer_type
<
T
>::
value
>
token
;
std
::
tuple
<
const
Ts
&
...
>
peek
()
{
CAF_REQUIRE
(
dest_
!=
nullptr
);
auto
ptr
=
dest_
->
mailbox
().
peek
();
CAF_REQUIRE
(
ptr
->
content
().
match_elements
<
Ts
...
>
());
return
ptr
->
content
().
get_as_tuple
<
Ts
...
>
();
}
protected:
void
run_once
()
{
if
(
dynamic_cast
<
caf
::
blocking_actor
*>
(
dest_
)
==
nullptr
)
sched_
.
run_once
();
else
// remove message from mailbox
delete
dest_
->
mailbox
().
try_pop
();
}
Derived
&
dref
()
{
return
*
static_cast
<
Derived
*>
(
this
);
}
// denotes whether destination is a mock actor, i.e., a scoped_actor without
// functionality other than checking outputs of other actors
caf
::
scheduler
::
test_coordinator
&
sched_
;
bool
mock_dest_
;
caf
::
strong_actor_ptr
src_
;
caf
::
local_actor
*
dest_
;
};
template
<
class
...
Ts
>
class
expect_clause
:
public
expect_clause_base
<
expect_clause
<
Ts
...
>>
{
public:
template
<
class
...
Us
>
expect_clause
(
Us
&&
...
xs
)
:
expect_clause_base
<
expect_clause
<
Ts
...
>>
(
std
::
forward
<
Us
>
(
xs
)...)
{
// nop
}
template
<
class
...
Us
>
void
with
(
Us
&&
...
xs
)
{
auto
tmp
=
std
::
make_tuple
(
std
::
forward
<
Ts
>
(
xs
)...);
elementwise_compare_inspector
<
decltype
(
tmp
)
>
inspector
{
tmp
};
auto
ys
=
this
->
template
peek
<
Ts
...>();
CAF_CHECK
(
inspector
(
get
<
0
>
(
ys
)));
this
->
run_once
();
}
};
/// The single-argument expect-clause allows to automagically unwrap T
/// if it's a variant-like wrapper.
template
<
class
T
>
class
expect_clause
<
T
>
:
public
expect_clause_base
<
expect_clause
<
T
>>
{
public:
template
<
class
...
Us
>
expect_clause
(
Us
&&
...
xs
)
:
expect_clause_base
<
expect_clause
<
T
>>
(
std
::
forward
<
Us
>
(
xs
)...)
{
// nop
}
template
<
class
...
Us
>
void
with
(
Us
&&
...
xs
)
{
std
::
integral_constant
<
bool
,
has_outer_type
<
T
>::
value
>
token
;
auto
tmp
=
std
::
make_tuple
(
std
::
forward
<
Us
>
(
xs
)...);
with_content
(
token
,
tmp
);
sched_
.
run_once
();
this
->
run_once
();
}
private:
template
<
class
U
>
void
with_content
(
std
::
integral_constant
<
bool
,
false
>
,
const
U
&
x
)
{
elementwise_compare_inspector
<
U
>
inspector
{
x
};
CAF_CHECK
(
inspector
(
const_cast
<
T
&>
(
sched_
.
peek
<
T
>
())));
auto
xs
=
this
->
template
peek
<
T
>();
CAF_CHECK
(
inspector
(
get
<
0
>
(
xs
)));
}
template
<
class
U
>
void
with_content
(
std
::
integral_constant
<
bool
,
true
>
,
const
U
&
x
)
{
elementwise_compare_inspector
<
U
>
inspector
{
x
};
auto
&
y
=
sched_
.
peek
<
typename
T
::
outer_type
>
();
CAF_CHECK
(
inspector
(
const_cast
<
T
&>
(
get
<
T
>
(
y
)
)));
auto
xs
=
this
->
template
peek
<
typename
T
::
outer_type
>();
CAF_CHECK
(
inspector
(
get
<
0
>
(
xs
)));
}
caf
::
scheduler
::
test_coordinator
&
sched_
;
caf
::
strong_actor_ptr
src_
;
};
template
<
class
Config
=
caf
::
actor_system_config
>
...
...
@@ -207,15 +306,18 @@ struct test_coordinator_fixture {
return
dynamic_cast
<
T
&>
(
*
ptr
);
}
template
<
class
T
>
expect_clause
<
T
>
expect
()
{
template
<
class
...
Ts
>
expect_clause
<
Ts
...
>
expect
()
{
return
{
sched
};
}
};
}
// namespace <anonymous>
#define expect(type, fields) \
CAF_MESSAGE("expect(" << #type << ")." << #fields); \
expect<type>().fields
#define CAF_EXPAND(x) x
#define CAF_DSL_LIST(...) __VA_ARGS__
#define expect(types, fields) \
CAF_MESSAGE("expect" << #types << "." << #fields); \
expect< CAF_EXPAND(CAF_DSL_LIST types) >().fields
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment