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
3db0335c
Commit
3db0335c
authored
Jul 21, 2018
by
Joseph Noir
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Add basic test for timeout with ordering policy
parent
a0c40604
Changes
1
Hide whitespace changes
Inline
Side-by-side
Showing
1 changed file
with
183 additions
and
23 deletions
+183
-23
libcaf_io/test/protocol_policy.cpp
libcaf_io/test/protocol_policy.cpp
+183
-23
No files found.
libcaf_io/test/protocol_policy.cpp
View file @
3db0335c
...
...
@@ -32,6 +32,8 @@
// TODO: {receive_buffer => byte_buffer} (and use `byte` instead of `char`)
#include "caf/io/network/receive_buffer.hpp"
#include "caf/detail/enum_to_string.hpp"
using
namespace
caf
;
using
namespace
caf
::
io
;
...
...
@@ -48,6 +50,13 @@ struct protocol_policy_base;
template
<
class
T
>
struct
protocol_policy
;
template
<
class
T
>
struct
newb
;
// -- atoms --------------------------------------------------------------------
using
ordering_atom
=
atom_constant
<
atom
(
"ordering"
)
>
;
// -- aliases ------------------------------------------------------------------
using
byte_buffer
=
network
::
receive_buffer
;
...
...
@@ -60,7 +69,7 @@ struct basp_header {
};
struct
ordering_header
{
int32_t
seq_nr
;
u
int32_t
seq_nr
;
};
// -- message types ------------------------------------------------------------
...
...
@@ -71,7 +80,7 @@ struct new_basp_message {
size_t
payload_size
;
};
// --
new broker classes
-------------------------------------------------------
// --
transport policy --
-------------------------------------------------------
struct
transport_policy
{
virtual
~
transport_policy
()
{
...
...
@@ -88,11 +97,13 @@ struct transport_policy {
template
<
class
T
>
expected
<
T
>
read_some
(
protocol_policy
<
T
>&
policy
)
{
optional
<
T
>
read_some
(
newb
<
T
>*
parent
,
protocol_policy
<
T
>&
policy
)
{
auto
err
=
read_some
();
if
(
err
)
return
err
;
return
policy
.
read
(
receive_buffer
.
data
(),
receive_buffer
.
size
());
if
(
err
)
{
// Call something on parent?
return
none
;
}
return
policy
.
read
(
parent
,
receive_buffer
.
data
(),
receive_buffer
.
size
());
}
virtual
error
read_some
()
{
...
...
@@ -105,6 +116,8 @@ struct transport_policy {
using
transport_policy_ptr
=
std
::
unique_ptr
<
transport_policy
>
;
// -- accept policy ------------------------------------------------------------
struct
accept_policy
{
virtual
~
accept_policy
()
{
// nop
...
...
@@ -113,6 +126,8 @@ struct accept_policy {
virtual
void
init
(
newb_base
&
)
=
0
;
};
// -- protocol policies --------------------------------------------------------
struct
protocol_policy_base
{
virtual
~
protocol_policy_base
()
{
// nop
...
...
@@ -129,11 +144,14 @@ struct protocol_policy : protocol_policy_base {
// nop
}
virtual
expected
<
T
>
read
(
char
*
bytes
,
size_t
count
)
=
0
;
virtual
optional
<
T
>
read
(
newb
<
T
>*
parent
,
char
*
bytes
,
size_t
count
)
=
0
;
virtual
optional
<
T
>
timeout
(
newb
<
T
>*
parent
,
caf
::
message
&
msg
)
=
0
;
void
write_header
(
byte_buffer
&
,
size_t
)
override
{
// nop
}
};
template
<
class
T
>
...
...
@@ -143,8 +161,10 @@ struct basp_policy {
static
constexpr
size_t
header_size
=
sizeof
(
basp_header
);
static
constexpr
size_t
offset
=
header_size
;
using
type
=
new_basp_message
;
using
result_type
=
expected
<
new_basp_message
>
;
result_type
read
(
char
*
bytes
,
size_t
count
)
{
using
result_type
=
optional
<
new_basp_message
>
;
//newb<type>* parent;
result_type
read
(
newb
<
type
>*
,
char
*
bytes
,
size_t
count
)
{
new_basp_message
msg
;
memcpy
(
&
msg
.
header
.
from
,
bytes
,
sizeof
(
msg
.
header
.
from
));
memcpy
(
&
msg
.
header
.
to
,
bytes
+
sizeof
(
msg
.
header
.
from
),
sizeof
(
msg
.
header
.
to
));
...
...
@@ -152,7 +172,10 @@ struct basp_policy {
msg
.
payload_size
=
count
-
header_size
;
return
msg
;
}
scoped_execution_unit
context
;
result_type
timeout
(
newb
<
type
>*
,
caf
::
message
&
)
{
return
none
;
}
};
template
<
class
Next
>
...
...
@@ -161,13 +184,45 @@ struct ordering {
static
constexpr
size_t
offset
=
Next
::
offset
+
header_size
;
using
type
=
typename
Next
::
type
;
using
result_type
=
typename
Next
::
result_type
;
uint32_t
next_seq
=
0
;
Next
next
;
result_type
read
(
char
*
bytes
,
size_t
count
)
{
std
::
unordered_map
<
uint32_t
,
std
::
vector
<
char
>>
pending
;
result_type
read
(
newb
<
type
>*
parent
,
char
*
bytes
,
size_t
count
)
{
// TODO: What to do if we want to deliver multiple messages? For
// example when our buffer a missing message arrives and we
// can just deliver everything in our buffer?
uint32_t
seq
;
memcpy
(
&
seq
,
bytes
,
sizeof
(
seq
));
return
next
.
read
(
bytes
+
header_size
,
count
-
header_size
);
if
(
seq
!=
next_seq
)
{
CAF_MESSAGE
(
"adding message to pending "
);
// TODO: Only works if we have datagrams.
pending
[
seq
]
=
std
::
vector
<
char
>
(
bytes
+
header_size
,
bytes
+
count
);
parent
->
set_timeout
(
std
::
chrono
::
seconds
(
2
),
caf
::
make_message
(
ordering_atom
::
value
,
seq
));
return
none
;
}
next_seq
++
;
return
next
.
read
(
parent
,
bytes
+
header_size
,
count
-
header_size
);
}
result_type
timeout
(
newb
<
type
>*
parent
,
caf
::
message
&
msg
)
{
// TODO: Same as above.
auto
matched
=
false
;
result_type
was_pending
=
none
;
msg
.
apply
([
&
](
ordering_atom
,
uint32_t
seq
)
{
matched
=
true
;
if
(
pending
.
count
(
seq
)
>
0
)
{
CAF_MESSAGE
(
"found pending message"
);
auto
&
buf
=
pending
[
seq
];
was_pending
=
next
.
read
(
parent
,
buf
.
data
(),
buf
.
size
());
}
});
if
(
matched
)
return
was_pending
;
return
next
.
timeout
(
parent
,
msg
);
}
scoped_execution_unit
context
;
};
template
<
class
T
>
...
...
@@ -177,15 +232,24 @@ struct protocol_policy_impl : protocol_policy<typename T::type> {
// nop
}
typename
T
::
result_type
read
(
char
*
bytes
,
size_t
count
)
override
{
return
impl
.
read
(
bytes
,
count
);
typename
T
::
result_type
read
(
newb
<
typename
T
::
type
>*
parent
,
char
*
bytes
,
size_t
count
)
override
{
return
impl
.
read
(
parent
,
bytes
,
count
);
}
size_t
offset
()
const
noexcept
override
{
return
T
::
offset
;
}
typename
T
::
result_type
timeout
(
newb
<
typename
T
::
type
>*
parent
,
caf
::
message
&
msg
)
override
{
return
impl
.
timeout
(
parent
,
msg
);
}
};
// -- new broker classes -------------------------------------------------------
/// Returned by funtion wr_buf
struct
write_handle
{
protocol_policy_base
*
protocol
;
byte_buffer
*
buf
;
...
...
@@ -214,14 +278,15 @@ struct newb {
return
{
protocol
.
get
(),
buf
,
header_offset
};
}
// Send
void
flush
()
{
}
error
read_event
()
{
auto
maybe_msg
=
transport
->
read_some
(
*
protocol
);
auto
maybe_msg
=
transport
->
read_some
(
this
,
*
protocol
);
if
(
!
maybe_msg
)
return
std
::
move
(
maybe_msg
.
error
()
);
return
make_error
(
sec
::
unexpected_message
);
// TODO: create message on the stack and call message handler
handle
(
*
maybe_msg
);
return
none
;
...
...
@@ -231,7 +296,31 @@ struct newb {
// transport->write_some();
}
// Protocol policies can set timeouts using a custom message.
template
<
class
Rep
=
int
,
class
Period
=
std
::
ratio
<
1
>
>
void
set_timeout
(
std
::
chrono
::
duration
<
Rep
,
Period
>
,
caf
::
message
msg
)
{
// TODO: Once this is an actor send yourself a delayed messge.
// And on receict call ...
set_timeout_impl
(
std
::
move
(
msg
));
}
// Called on self when a timeout is received.
error
timeout_event
(
caf
::
message
&
msg
)
{
auto
maybe_msg
=
protocol
->
timeout
(
this
,
msg
);
if
(
!
maybe_msg
)
return
make_error
(
sec
::
unexpected_message
);
handle
(
*
maybe_msg
);
return
none
;
}
// Allow protocol policies to enqueue a data for sending.
// Probably required for reliability.
// void direct_enqueue(char* bytes, size_t count);
virtual
void
handle
(
Message
&
msg
)
=
0
;
// TODO: Only here for some first tests.
virtual
void
set_timeout_impl
(
caf
::
message
)
=
0
;
};
struct
basp_newb
:
newb
<
new_basp_message
>
{
...
...
@@ -259,14 +348,22 @@ struct newb_acceptor {
};
*/
// client: sys.middleman().spawn_client<protocol_policy>(sock, std::move(transport_protocol_policy_impl), my_client);
// server: sys.middleman().spawn_server<protocol_policy>(sock, std::move(accept_protocol_policy_impl), my_server);
// client: sys.middleman().spawn_client<protocol_policy>(sock,
// std::move(transport_protocol_policy_impl), my_client);
// server: sys.middleman().spawn_server<protocol_policy>(sock,
// std::move(accept_protocol_policy_impl), my_server);
// -- test classes -------------------------------------------------------------
struct
dummy_basp_newb
:
newb
<
new_basp_message
>
{
void
handle
(
new_basp_message
&
received_msg
)
override
{
msg
=
received_msg
;
}
void
set_timeout_impl
(
caf
::
message
msg
)
override
{
timeout_messages
.
emplace_back
(
std
::
move
(
msg
));
}
std
::
vector
<
caf
::
message
>
timeout_messages
;
new_basp_message
msg
;
};
...
...
@@ -284,10 +381,17 @@ struct fixture {
CAF_TEST_FIXTURE_SCOPE
(
protocol_policy_tests
,
fixture
)
CAF_TEST
(
ordering
and
basp
)
{
CAF_TEST
(
ordering
and
basp
read
event
)
{
// Read process:
// - read event happens
// - read_event() called on newb
// - read_some(protocol&) called on transport policy
// - transport policies reads from network layer
// - calls read on protocol policy
// - the basp policy fills the expected result message with data
CAF_MESSAGE
(
"create some values for our buffer"
);
ordering_header
ohdr
{
13
};
basp_header
bhdr
{
41
,
43
};
ordering_header
ohdr
{
0
};
basp_header
bhdr
{
13
,
42
};
int
payload
=
1337
;
CAF_MESSAGE
(
"copy them into the buffer"
);
auto
&
buf
=
self
.
transport
->
receive_buffer
;
...
...
@@ -303,7 +407,8 @@ CAF_TEST(ordering and basp) {
offset
+=
sizeof
(
basp_header
);
memcpy
(
buf
.
data
()
+
offset
,
&
payload
,
sizeof
(
payload
));
CAF_MESSAGE
(
"trigger a read event"
);
self
.
read_event
();
auto
err
=
self
.
read_event
();
CAF_REQUIRE
(
!
err
);
CAF_MESSAGE
(
"check the basp header and payload"
);
CAF_CHECK_EQUAL
(
self
.
msg
.
header
.
from
,
bhdr
.
from
);
CAF_CHECK_EQUAL
(
self
.
msg
.
header
.
to
,
bhdr
.
to
);
...
...
@@ -313,4 +418,59 @@ CAF_TEST(ordering and basp) {
CAF_CHECK_EQUAL
(
return_payload
,
payload
);
}
CAF_TEST
(
ordering
and
basp
read
event
with
timeout
)
{
// Read process:
// - read event happens
// - read_event() called on newb
// - read_some(protocol&) called on transport policy
// - transport policies reads from network layer
// - calls read on protocol policy
// - the ordering policy sets a timeout
// -
CAF_MESSAGE
(
"create some values for our buffer"
);
// Should be an unexpected sequence number and lead to an error.
ordering_header
ohdr
{
1
};
basp_header
bhdr
{
13
,
42
};
int
payload
=
1337
;
CAF_MESSAGE
(
"copy them into the buffer"
);
auto
&
buf
=
self
.
transport
->
receive_buffer
;
// Make sure the buffer is big enough.
buf
.
resize
(
sizeof
(
ordering_header
)
+
sizeof
(
basp_header
)
+
sizeof
(
payload
));
// Track an offset for writing.
size_t
offset
=
0
;
memcpy
(
buf
.
data
()
+
offset
,
&
ohdr
,
sizeof
(
ordering_header
));
offset
+=
sizeof
(
ordering_header
);
memcpy
(
buf
.
data
()
+
offset
,
&
bhdr
,
sizeof
(
basp_header
));
offset
+=
sizeof
(
basp_header
);
memcpy
(
buf
.
data
()
+
offset
,
&
payload
,
sizeof
(
payload
));
CAF_MESSAGE
(
"trigger a read event, expecting an error"
);
auto
err
=
self
.
read_event
();
CAF_REQUIRE
(
err
);
CAF_MESSAGE
(
"check if we have a pending timeout now"
);
CAF_REQUIRE
(
!
self
.
timeout_messages
.
empty
());
auto
&
timeout_msg
=
self
.
timeout_messages
.
back
();
auto
read_message
=
false
;
timeout_msg
.
apply
([
&
](
ordering_atom
,
uint32_t
seq
)
{
if
(
seq
==
ohdr
.
seq_nr
)
read_message
=
true
;
});
CAF_REQUIRE
(
read_message
);
CAF_MESSAGE
(
"trigger timeout"
);
err
=
self
.
timeout_event
(
timeout_msg
);
CAF_REQUIRE
(
!
err
);
CAF_MESSAGE
(
"check delivered message"
);
CAF_CHECK_EQUAL
(
self
.
msg
.
header
.
from
,
bhdr
.
from
);
CAF_CHECK_EQUAL
(
self
.
msg
.
header
.
to
,
bhdr
.
to
);
CAF_CHECK_EQUAL
(
self
.
msg
.
payload_size
,
sizeof
(
payload
));
int
return_payload
=
0
;
memcpy
(
&
return_payload
,
self
.
msg
.
payload
,
self
.
msg
.
payload_size
);
CAF_CHECK_EQUAL
(
return_payload
,
payload
);
}
CAF_TEST
(
ordering
and
basp
write
event
)
{
CAF_MESSAGE
(
"Not implemented"
);
}
CAF_TEST_FIXTURE_SCOPE_END
()
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