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
c525c605
Unverified
Commit
c525c605
authored
Oct 15, 2019
by
Joseph Noir
Committed by
GitHub
Oct 15, 2019
Browse files
Options
Browse Files
Download
Plain Diff
Merge pull request #931
Fix several issues with config values
parents
11c4eaca
760b0989
Changes
9
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
9 changed files
with
494 additions
and
182 deletions
+494
-182
libcaf_core/caf/actor_system_config.hpp
libcaf_core/caf/actor_system_config.hpp
+11
-4
libcaf_core/caf/config_value.hpp
libcaf_core/caf/config_value.hpp
+1
-0
libcaf_core/caf/config_value_field.hpp
libcaf_core/caf/config_value_field.hpp
+6
-9
libcaf_core/caf/config_value_object_access.hpp
libcaf_core/caf/config_value_object_access.hpp
+9
-11
libcaf_core/caf/detail/config_value_field_base.hpp
libcaf_core/caf/detail/config_value_field_base.hpp
+108
-0
libcaf_core/caf/detail/config_value_field_impl.hpp
libcaf_core/caf/detail/config_value_field_impl.hpp
+45
-91
libcaf_core/caf/detail/parse.hpp
libcaf_core/caf/detail/parse.hpp
+29
-21
libcaf_core/test/actor_system_config.cpp
libcaf_core/test/actor_system_config.cpp
+220
-40
libcaf_core/test/make_config_value_field.cpp
libcaf_core/test/make_config_value_field.cpp
+65
-6
No files found.
libcaf_core/caf/actor_system_config.hpp
View file @
c525c605
...
...
@@ -415,14 +415,14 @@ private:
const
settings
&
content
(
const
actor_system_config
&
cfg
);
/// Tries to retrieve the value associated to `name` from `cfg`.
/// @relates
config_value
/// @relates
actor_system_config
template
<
class
T
>
optional
<
T
>
get_if
(
const
actor_system_config
*
cfg
,
string_view
name
)
{
return
get_if
<
T
>
(
&
content
(
*
cfg
),
name
);
}
/// Retrieves the value associated to `name` from `cfg`.
/// @relates
config_value
/// @relates
actor_system_config
template
<
class
T
>
T
get
(
const
actor_system_config
&
cfg
,
string_view
name
)
{
return
get
<
T
>
(
content
(
cfg
),
name
);
...
...
@@ -430,7 +430,7 @@ T get(const actor_system_config& cfg, string_view name) {
/// Retrieves the value associated to `name` from `cfg` or returns
/// `default_value`.
/// @relates
config_value
/// @relates
actor_system_config
template
<
class
T
,
class
=
typename
std
::
enable_if
<
!
std
::
is_pointer
<
T
>
::
value
&&
!
std
::
is_convertible
<
T
,
string_view
>::
value
>::
type
>
...
...
@@ -440,10 +440,17 @@ T get_or(const actor_system_config& cfg, string_view name, T default_value) {
/// Retrieves the value associated to `name` from `cfg` or returns
/// `default_value`.
/// @relates
config_value
/// @relates
actor_system_config
inline
std
::
string
get_or
(
const
actor_system_config
&
cfg
,
string_view
name
,
string_view
default_value
)
{
return
get_or
(
content
(
cfg
),
name
,
default_value
);
}
/// Returns whether `xs` associates a value of type `T` to `name`.
/// @relates actor_system_config
template
<
class
T
>
bool
holds_alternative
(
const
actor_system_config
&
cfg
,
string_view
name
)
{
return
holds_alternative
<
T
>
(
content
(
cfg
),
name
);
}
}
// namespace caf
libcaf_core/caf/config_value.hpp
View file @
c525c605
...
...
@@ -259,6 +259,7 @@ CAF_DEFAULT_CONFIG_VALUE_ACCESS(bool, "boolean");
CAF_DEFAULT_CONFIG_VALUE_ACCESS
(
double
,
"real64"
);
CAF_DEFAULT_CONFIG_VALUE_ACCESS
(
atom_value
,
"atom"
);
CAF_DEFAULT_CONFIG_VALUE_ACCESS
(
timespan
,
"timespan"
);
CAF_DEFAULT_CONFIG_VALUE_ACCESS
(
uri
,
"uri"
);
CAF_DEFAULT_CONFIG_VALUE_ACCESS
(
config_value
::
list
,
"list"
);
CAF_DEFAULT_CONFIG_VALUE_ACCESS
(
config_value
::
dictionary
,
"dictionary"
);
...
...
libcaf_core/caf/config_value_field.hpp
View file @
c525c605
...
...
@@ -33,12 +33,6 @@ public:
// -- observers --------------------------------------------------------------
/// Checks whether `x` matches the type of this field.
virtual
bool
type_check
(
const
config_value
&
x
)
const
noexcept
=
0
;
/// Returns whether this field in `object` contains valid data.
virtual
bool
valid
(
const
Object
&
object
)
const
noexcept
=
0
;
/// Returns whether this field has a default value.
virtual
bool
has_default
()
const
noexcept
=
0
;
...
...
@@ -48,11 +42,14 @@ public:
/// Returns the value of this field in `object` as config value.
virtual
config_value
get
(
const
Object
&
object
)
const
=
0
;
/// Returns whether calling `set` with `x` would succeed.
virtual
bool
valid_input
(
const
config_value
&
x
)
const
=
0
;
// -- modifiers --------------------------------------------------------------
///
Sets
this field in `object` to `x`.
/// @
pre `can_set(x)`
virtual
void
set
(
Object
&
object
,
const
config_value
&
x
)
const
=
0
;
///
Tries to set
this field in `object` to `x`.
/// @
returns `true` on success, `false` otherwise.
virtual
bool
set
(
Object
&
object
,
const
config_value
&
x
)
const
=
0
;
/// Restores the default value for this field in `object`.
/// @pre `has_default()`
...
...
libcaf_core/caf/config_value_object_access.hpp
View file @
c525c605
...
...
@@ -48,17 +48,19 @@ struct config_value_object_access {
if
(
!
dict
)
return
false
;
for
(
auto
field
:
Trait
::
fields
())
{
auto
value
=
caf
::
get_if
(
dict
,
field
->
name
());
if
(
!
value
)
{
if
(
auto
value
=
caf
::
get_if
(
dict
,
field
->
name
()))
{
if
(
dst
)
{
if
(
!
field
->
set
(
*
dst
,
*
value
))
return
false
;
}
else
{
if
(
!
field
->
valid_input
(
*
value
))
return
false
;
}
}
else
{
if
(
!
field
->
has_default
())
return
false
;
if
(
dst
)
field
->
set_default
(
*
dst
);
}
else
if
(
field
->
type_check
(
*
value
))
{
if
(
dst
)
field
->
set
(
*
dst
,
*
value
);
}
else
{
return
false
;
}
}
return
true
;
...
...
@@ -156,10 +158,6 @@ struct config_value_object_access {
ps
.
code
=
pec
::
unexpected_eof
;
return
;
}
if
(
!
fptr
->
valid
(
x
))
{
ps
.
code
=
pec
::
illegal_argument
;
return
;
}
result
[
fptr
->
name
()]
=
fptr
->
get
(
x
);
}
while
(
ps
.
consume
(
','
));
if
(
!
ps
.
consume
(
'}'
))
{
...
...
libcaf_core/caf/detail/config_value_field_base.hpp
0 → 100644
View file @
c525c605
/******************************************************************************
* ____ _ _____ *
* / ___| / \ | ___| C++ *
* | | / _ \ | |_ Actor *
* | |___ / ___ \| _| Framework *
* \____/_/ \_|_| *
* *
* Copyright 2011-2019 Dominik Charousset *
* *
* 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. *
******************************************************************************/
#pragma once
#include "caf/config_value.hpp"
#include "caf/config_value_field.hpp"
#include "caf/detail/dispatch_parse_cli.hpp"
#include "caf/optional.hpp"
namespace
caf
{
namespace
detail
{
template
<
class
Object
,
class
Value
>
class
config_value_field_base
:
public
config_value_field
<
Object
>
{
public:
using
super
=
config_value_field
<
Object
>
;
using
object_type
=
typename
super
::
object_type
;
using
value_type
=
Value
;
using
predicate_type
=
bool
(
*
)(
const
value_type
&
);
config_value_field_base
(
string_view
name
,
optional
<
value_type
>
default_value
,
predicate_type
predicate
)
:
name_
(
name
),
default_value_
(
std
::
move
(
default_value
)),
predicate_
(
predicate
)
{
// nop
}
config_value_field_base
(
config_value_field_base
&&
)
=
default
;
bool
has_default
()
const
noexcept
override
{
return
static_cast
<
bool
>
(
default_value_
);
}
string_view
name
()
const
noexcept
override
{
return
name_
;
}
config_value
get
(
const
object_type
&
object
)
const
override
{
using
access
=
caf
::
select_config_value_access_t
<
value_type
>
;
return
config_value
{
access
::
convert
(
get_value
(
object
))};
}
bool
valid_input
(
const
config_value
&
x
)
const
override
{
if
(
!
predicate_
)
return
holds_alternative
<
value_type
>
(
x
);
if
(
auto
value
=
get_if
<
value_type
>
(
&
x
))
return
predicate_
(
*
value
);
return
false
;
}
bool
set
(
object_type
&
x
,
const
config_value
&
y
)
const
override
{
if
(
auto
value
=
get_if
<
value_type
>
(
&
y
))
{
if
(
predicate_
&&
!
predicate_
(
*
value
))
return
false
;
set_value
(
x
,
move_if_optional
(
value
));
return
true
;
}
return
false
;
}
void
set_default
(
object_type
&
x
)
const
override
{
set_value
(
x
,
*
default_value_
);
}
void
parse_cli
(
string_parser_state
&
ps
,
object_type
&
x
,
const
char
*
char_blacklist
)
const
override
{
value_type
tmp
;
dispatch_parse_cli
(
ps
,
tmp
,
char_blacklist
);
if
(
ps
.
code
<=
pec
::
trailing_character
)
{
if
(
predicate_
&&
!
predicate_
(
tmp
))
ps
.
code
=
pec
::
illegal_argument
;
else
set_value
(
x
,
std
::
move
(
tmp
));
}
}
virtual
const
value_type
&
get_value
(
const
object_type
&
object
)
const
=
0
;
virtual
void
set_value
(
object_type
&
object
,
value_type
value
)
const
=
0
;
protected:
string_view
name_
;
optional
<
value_type
>
default_value_
;
predicate_type
predicate_
;
};
}
// namespace detail
}
// namespace caf
libcaf_core/caf/detail/config_value_field_impl.hpp
View file @
c525c605
...
...
@@ -23,6 +23,7 @@
#include "caf/config_value.hpp"
#include "caf/config_value_field.hpp"
#include "caf/detail/config_value_field_base.hpp"
#include "caf/detail/dispatch_parse_cli.hpp"
#include "caf/detail/parse.hpp"
#include "caf/detail/type_traits.hpp"
...
...
@@ -38,157 +39,110 @@ class config_value_field_impl;
// A config value with direct access to a field via member object pointer.
template
<
class
Value
,
class
Object
>
class
config_value_field_impl
<
Value
Object
::*>
:
public
config_value_field
<
Object
>
{
:
public
config_value_field
_base
<
Object
,
Value
>
{
public:
using
super
=
config_value_field_base
<
Object
,
Value
>
;
using
member_pointer
=
Value
Object
::*
;
using
object_type
=
Object
;
using
value_type
=
Value
;
using
predicate_
pointer
=
bool
(
*
)(
const
value_type
&
);
using
predicate_
type
=
bool
(
*
)(
const
value_type
&
);
constexpr
config_value_field_impl
(
string_view
name
,
member_pointer
ptr
,
optional
<
value_type
>
default_value
=
none
,
predicate_pointer
predicate
=
nullptr
)
:
name_
(
name
),
ptr_
(
ptr
),
default_value_
(
std
::
move
(
default_value
)),
predicate_
(
predicate
)
{
predicate_type
predicate
=
nullptr
)
:
super
(
name
,
std
::
move
(
default_value
),
predicate
),
ptr_
(
ptr
)
{
// nop
}
constexpr
config_value_field_impl
(
config_value_field_impl
&&
)
=
default
;
bool
type_check
(
const
config_value
&
x
)
const
noexcept
override
{
return
holds_alternative
<
value_type
>
(
x
);
}
bool
valid
(
const
object_type
&
x
)
const
noexcept
override
{
return
predicate_
?
predicate_
(
x
.
*
ptr_
)
:
true
;
}
void
set
(
object_type
&
x
,
const
config_value
&
y
)
const
override
{
x
.
*
ptr_
=
caf
::
get
<
value_type
>
(
y
);
}
config_value
get
(
const
object_type
&
x
)
const
override
{
using
access
=
select_config_value_access_t
<
value_type
>
;
return
config_value
{
access
::
convert
(
x
.
*
ptr_
)};
const
value_type
&
get_value
(
const
object_type
&
x
)
const
override
{
return
x
.
*
ptr_
;
}
void
parse_cli
(
string_parser_state
&
ps
,
object_type
&
x
,
const
char
*
char_blacklist
)
const
override
{
detail
::
dispatch_parse_cli
(
ps
,
x
.
*
ptr_
,
char_blacklist
);
}
string_view
name
()
const
noexcept
override
{
return
name_
;
}
bool
has_default
()
const
noexcept
override
{
return
static_cast
<
bool
>
(
default_value_
);
}
void
set_default
(
object_type
&
x
)
const
override
{
x
.
*
ptr_
=
*
default_value_
;
void
set_value
(
object_type
&
x
,
value_type
y
)
const
override
{
x
.
*
ptr_
=
std
::
move
(
y
);
}
private:
string_view
name_
;
member_pointer
ptr_
;
optional
<
value_type
>
default_value_
;
predicate_pointer
predicate_
;
};
template
<
class
Get
>
struct
config_value_field_
base
{
struct
config_value_field_
trait
{
using
trait
=
get_callable_trait_t
<
Get
>
;
static_assert
(
trait
::
num_args
==
1
,
"Get must take exactly one argument (the object)"
);
using
arg
_type
=
tl_head_t
<
typename
trait
::
arg_types
>
;
using
get_argument
_type
=
tl_head_t
<
typename
trait
::
arg_types
>
;
using
value_type
=
decay_t
<
typename
trait
::
resul
t_type
>
;
using
object_type
=
decay_t
<
get_argumen
t_type
>
;
using
type
=
config_value_field
<
decay_t
<
arg_type
>>
;
};
using
get_result_type
=
typename
trait
::
result_type
;
template
<
class
Get
>
using
config_value_field_base_t
=
typename
config_value_field_base
<
Get
>::
type
;
using
value_type
=
decay_t
<
get_result_type
>
;
}
;
// A config value with access to a field via getter and setter.
template
<
class
Get
,
class
Set
>
class
config_value_field_impl
<
std
::
pair
<
Get
,
Set
>>
:
public
config_value_field_base_t
<
Get
>
{
:
public
config_value_field_base
<
typename
config_value_field_trait
<
Get
>::
object_type
,
typename
config_value_field_trait
<
Get
>::
value_type
>
{
public:
using
super
=
config_value_field_base_t
<
Get
>
;
using
trait
=
config_value_field_trait
<
Get
>
;
using
object_type
=
typename
trait
::
object_type
;
using
object_type
=
typename
super
::
objec
t_type
;
using
get_result_type
=
typename
trait
::
get_resul
t_type
;
using
get_trait
=
get_callable_trait_t
<
Get
>
;
using
value_type
=
typename
trait
::
value_type
;
using
value_type
=
decay_t
<
typename
get_trait
::
result_type
>
;
using
predicate_type
=
bool
(
*
)(
const
value_type
&
)
;
using
predicate_pointer
=
bool
(
*
)(
const
value_type
&
)
;
using
super
=
config_value_field_base
<
object_type
,
value_type
>
;
constexpr
config_value_field_impl
(
string_view
name
,
Get
getter
,
Set
setter
,
optional
<
value_type
>
default_value
=
none
,
predicate_
pointer
predicate
=
nullptr
)
:
name_
(
nam
e
),
predicate_
type
predicate
=
nullptr
)
:
super
(
name
,
std
::
move
(
default_value
),
predicat
e
),
get_
(
std
::
move
(
getter
)),
set_
(
std
::
move
(
setter
)),
default_value_
(
std
::
move
(
default_value
)),
predicate_
(
predicate
)
{
set_
(
std
::
move
(
setter
))
{
// nop
}
constexpr
config_value_field_impl
(
config_value_field_impl
&&
)
=
default
;
bool
type_check
(
const
config_value
&
x
)
const
noexcept
override
{
return
holds_alternative
<
value_type
>
(
x
);
}
void
set
(
object_type
&
x
,
const
config_value
&
y
)
const
override
{
set_
(
x
,
caf
::
get
<
value_type
>
(
y
));
}
config_value
get
(
const
object_type
&
x
)
const
override
{
using
access
=
select_config_value_access_t
<
value_type
>
;
return
config_value
{
access
::
convert
(
get_
(
x
))};
}
bool
valid
(
const
object_type
&
x
)
const
noexcept
override
{
return
predicate_
?
predicate_
(
get_
(
x
))
:
true
;
const
value_type
&
get_value
(
const
object_type
&
x
)
const
override
{
bool_token
<
std
::
is_lvalue_reference
<
get_result_type
>::
value
>
token
;
return
get_value_impl
(
x
,
token
);
}
void
parse_cli
(
string_parser_state
&
ps
,
object_type
&
x
,
const
char
*
char_blacklist
)
const
override
{
value_type
tmp
;
detail
::
dispatch_parse_cli
(
ps
,
tmp
,
char_blacklist
);
if
(
ps
.
code
<=
pec
::
trailing_character
)
set_
(
x
,
std
::
move
(
tmp
));
void
set_value
(
object_type
&
x
,
value_type
y
)
const
override
{
set_
(
x
,
std
::
move
(
y
));
}
string_view
name
()
const
noexcept
override
{
return
name_
;
}
bool
has_default
()
const
noexcept
override
{
return
static_cast
<
bool
>
(
default_value_
);
private:
template
<
class
O
>
const
value_type
&
get_value_impl
(
const
O
&
x
,
std
::
true_type
)
const
{
return
get_
(
x
);
}
void
set_default
(
object_type
&
x
)
const
override
{
set_
(
x
,
*
default_value_
);
template
<
class
O
>
const
value_type
&
get_value_impl
(
const
O
&
x
,
std
::
false_type
)
const
{
dummy_
=
get_
(
x
);
return
dummy_
;
}
private:
string_view
name_
;
Get
get_
;
Set
set_
;
optional
<
value_type
>
default_value_
;
predicate_pointer
predicate_
;
mutable
value_type
dummy_
;
};
}
// namespace detail
...
...
libcaf_core/caf/detail/parse.hpp
View file @
c525c605
...
...
@@ -107,30 +107,11 @@ void parse_element(string_parser_state& ps, std::string& x,
template
<
class
T
>
enable_if_t
<!
is_pair
<
T
>::
value
>
parse_element
(
string_parser_state
&
ps
,
T
&
x
,
const
char
*
)
{
parse
(
ps
,
x
);
}
const
char
*
);
template
<
class
First
,
class
Second
,
size_t
N
>
void
parse_element
(
string_parser_state
&
ps
,
std
::
pair
<
First
,
Second
>&
kvp
,
const
char
(
&
char_blacklist
)[
N
])
{
static_assert
(
N
>
0
,
"empty array"
);
// TODO: consider to guard the blacklist computation with
// `if constexpr (is_same_v<First, string>)` when switching to C++17.
char
key_blacklist
[
N
+
1
];
if
(
N
>
1
)
memcpy
(
key_blacklist
,
char_blacklist
,
N
-
1
);
key_blacklist
[
N
-
1
]
=
'='
;
key_blacklist
[
N
]
=
'\0'
;
parse_element
(
ps
,
kvp
.
first
,
key_blacklist
);
if
(
ps
.
code
>
pec
::
trailing_character
)
return
;
if
(
!
ps
.
consume
(
'='
))
{
ps
.
code
=
pec
::
unexpected_character
;
return
;
}
parse_element
(
ps
,
kvp
.
second
,
char_blacklist
);
}
const
char
(
&
char_blacklist
)[
N
]);
template
<
class
T
>
enable_if_tt
<
is_iterable
<
T
>>
parse
(
string_parser_state
&
ps
,
T
&
xs
)
{
...
...
@@ -177,6 +158,33 @@ enable_if_tt<is_iterable<T>> parse(string_parser_state& ps, T& xs) {
ps
.
code
=
ps
.
at_end
()
?
pec
::
success
:
pec
::
trailing_character
;
}
template
<
class
T
>
enable_if_t
<!
is_pair
<
T
>::
value
>
parse_element
(
string_parser_state
&
ps
,
T
&
x
,
const
char
*
)
{
parse
(
ps
,
x
);
}
template
<
class
First
,
class
Second
,
size_t
N
>
void
parse_element
(
string_parser_state
&
ps
,
std
::
pair
<
First
,
Second
>&
kvp
,
const
char
(
&
char_blacklist
)[
N
])
{
static_assert
(
N
>
0
,
"empty array"
);
// TODO: consider to guard the blacklist computation with
// `if constexpr (is_same_v<First, string>)` when switching to C++17.
char
key_blacklist
[
N
+
1
];
if
(
N
>
1
)
memcpy
(
key_blacklist
,
char_blacklist
,
N
-
1
);
key_blacklist
[
N
-
1
]
=
'='
;
key_blacklist
[
N
]
=
'\0'
;
parse_element
(
ps
,
kvp
.
first
,
key_blacklist
);
if
(
ps
.
code
>
pec
::
trailing_character
)
return
;
if
(
!
ps
.
consume
(
'='
))
{
ps
.
code
=
pec
::
unexpected_character
;
return
;
}
parse_element
(
ps
,
kvp
.
second
,
char_blacklist
);
}
// -- convenience functions ----------------------------------------------------
template
<
class
T
>
...
...
libcaf_core/test/actor_system_config.cpp
View file @
c525c605
This diff is collapsed.
Click to expand it.
libcaf_core/test/make_config_value_field.cpp
View file @
c525c605
...
...
@@ -22,6 +22,7 @@
#include "caf/test/dsl.hpp"
#include "caf/actor_system_config.hpp"
#include "caf/config_option_set.hpp"
#include "caf/config_value_object_access.hpp"
...
...
@@ -130,15 +131,12 @@ struct fixture {
foobar
x
;
CAF_CHECK_EQUAL
(
foo_field
.
name
(),
"foo"
);
CAF_REQUIRE
(
foo_field
.
has_default
());
CAF_CHECK
(
foo_field
.
valid
(
x
));
CAF_CHECK_EQUAL
(
foo_field
.
get
(
x
),
config_value
(
0
));
foo_field
.
set_default
(
x
);
CAF_CHECK_EQUAL
(
foo_field
.
get
(
x
),
config_value
(
42
));
CAF_CHECK
(
!
foo_field
.
type_check
(
config_value
(
1.
)));
CAF_CHECK
(
foo_field
.
type_check
(
config_value
(
-
1
)));
foo_field
.
set
(
x
,
config_value
(
-
1
));
CAF_CHECK_EQUAL
(
foo_field
.
get
(
x
),
config_value
(
-
1
));
CAF_CHECK
(
!
foo_field
.
valid
(
x
));
CAF_CHECK
(
!
foo_field
.
valid_input
(
config_value
(
1.
)));
CAF_CHECK
(
!
foo_field
.
valid_input
(
config_value
(
-
1
)));
CAF_CHECK
(
!
foo_field
.
set
(
x
,
config_value
(
-
1
)));
string_view
input
=
"123"
;
string_parser_state
ps
{
input
.
begin
(),
input
.
end
()};
foo_field
.
parse_cli
(
ps
,
x
);
...
...
@@ -257,4 +255,65 @@ CAF_TEST(object access from CLI arguments - foobar_foobar) {
fbfb
({
123
,
"hello"
},
{
1
,
"world!"
}));
}
namespace
{
constexpr
const
char
*
config_text
=
R"__(
arg1 = {
foo = 42
bar = "Don't panic!"
}
arg2 = {
x = {
foo = 1
bar = "hello"
}
y = {
foo = 2
bar = "world"
}
}
)__"
;
struct
test_config
:
actor_system_config
{
test_config
()
{
opt_group
{
custom_options_
,
"global"
}
.
add
(
fb
,
"arg1,1"
,
"some foobar"
)
.
add
(
fbfb
,
"arg2,2"
,
"somme foobar-foobar"
);
}
foobar
fb
;
foobar_foobar
fbfb
;
};
}
// namespace
CAF_TEST
(
object
access
from
actor
system
config
-
file
input
)
{
test_config
cfg
;
std
::
istringstream
in
{
config_text
};
if
(
auto
err
=
cfg
.
parse
(
0
,
nullptr
,
in
))
CAF_FAIL
(
"cfg.parse failed: "
<<
cfg
.
render
(
err
));
CAF_CHECK_EQUAL
(
cfg
.
fb
.
foo
,
42
);
CAF_CHECK_EQUAL
(
cfg
.
fb
.
bar
,
"Don't panic!"
);
CAF_CHECK_EQUAL
(
cfg
.
fbfb
.
x
.
foo
,
1
);
CAF_CHECK_EQUAL
(
cfg
.
fbfb
.
y
.
foo
,
2
);
CAF_CHECK_EQUAL
(
cfg
.
fbfb
.
x
.
bar
,
"hello"
);
CAF_CHECK_EQUAL
(
cfg
.
fbfb
.
y
.
bar
,
"world"
);
}
CAF_TEST
(
object
access
from
actor
system
config
-
file
input
and
arguments
)
{
std
::
vector
<
std
::
string
>
args
{
"-2"
,
"{y = {bar = CAF, foo = 20}, x = {foo = 10, bar = hello}}"
,
};
test_config
cfg
;
std
::
istringstream
in
{
config_text
};
if
(
auto
err
=
cfg
.
parse
(
std
::
move
(
args
),
in
))
CAF_FAIL
(
"cfg.parse failed: "
<<
cfg
.
render
(
err
));
CAF_CHECK_EQUAL
(
cfg
.
fb
.
foo
,
42
);
CAF_CHECK_EQUAL
(
cfg
.
fb
.
bar
,
"Don't panic!"
);
CAF_CHECK_EQUAL
(
cfg
.
fbfb
.
x
.
foo
,
10
);
CAF_CHECK_EQUAL
(
cfg
.
fbfb
.
y
.
foo
,
20
);
CAF_CHECK_EQUAL
(
cfg
.
fbfb
.
x
.
bar
,
"hello"
);
CAF_CHECK_EQUAL
(
cfg
.
fbfb
.
y
.
bar
,
"CAF"
);
}
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