SlideShare ist ein Scribd-Unternehmen logo
1 von 53
Your systems. Working as one.
Sumant Tambe, PhD
Principal Research Engineer and Microsoft VC++ MVP
Real-Time Innovations, Inc.
@sutambe
Oct. 3, 2015
10/4/2015 © 2015 RTI 2
LEESA 2008 Rx4DDS 2014 RefleX 2015
Alternative Title
10/4/2015 © 2015 RTI 3
Author
Blogger Open-Source
LEESA
(C++)
Rx4DDS
(C++11, C#, JavaScript)
(C++11)
Why should you care?
• If you write software for living and if you are
serious about any of the following
– Bug-free, Expressive code
– Productivity
• Modularity
• Reusability
• Extensibility
• Maintainability
– Performance/latency
• Multi-core scalability
– and having fun while doing that!
10/4/2015 © 2015 RTI 4
Agenda
• Property-based Testing
• The need for composable generators
• Design/Implementation of the generator library
• Mathematics of API design
– Functor, Monoid, and Monad
• Generators at compile-time (type generators)
10/4/2015 © 2015 RTI 5
What’s a Property
• Reversing a linked-list twice has no effect
– reverse(reverse(list)) == list
• Compression can make things smaller
– compress(input).size <= input.size
• Round-trip serialization/deserialization has no
effect
– deserialize(serialize(input)) == input
10/4/2015 © 2015 RTI 6
Testing RefleX
• RefleX is short for Reflection for DDS-Xtypes
• Serialization and Deserialization
– Serializes types and data
– Works off of C++ struct/classes directly
• C++11/14
• Link
10/4/2015 © 2015 RTI 7
RefleX Example
10/4/2015 © 2015 RTI 8
class ShapeType
{
std::string color_;
int x_, y_, shapesize_;
public:
ShapeType() {}
ShapeType(const std::string & color,
int x, int y, int shapesize)
: color_(color), x_(x), y_(y),
shapesize_(shapesize)
{}
std::string & color();
int & x();
int & y();
int & shapesize();
};
#include "reflex.h"
REFLEX_ADAPT_STRUCT(
ShapeType,
(std::string, color(), KEY)
(int, x())
(int, y())
(int, shapesize()))
A property-test in RefleX
10/4/2015 © 2015 RTI 9
template <class T>
void test_roundtrip_property(const T & in)
{
reflex::TypeManager<T> tm;
reflex::SafeDynamicData<T> safedd =
tm.create_dynamicdata(in);
reflex::read_dynamicdata(out, safedd);
assert(in == out);
}
Property-based Testing
• Complementary to traditional example-based testing
• Specify post-conditions that must hold no matter
what
• Encourages the programmer to think harder about
the code
• More declarative
• Need data generators to produce inputs
• Free reproducers!
– Good property-based testing frameworks shrink inputs to
minimal automatically
• Famous: Haskell’s QuickCheck, Scala’s ScalaTest
10/4/2015 © 2015 RTI 10
A property-test in RefleX
10/4/2015 © 2015 RTI 11
template <class T>
void test_roundtrip_property(const T & in)
{
reflex::TypeManager<T> tm;
reflex::SafeDynamicData<T> safedd =
tm.create_dynamicdata(in);
reflex::read_dynamicdata(out, safedd);
assert(in == out);
}
What’s the input data?
What are the input types?
10/4/2015 © 2015 RTI 12
Random Integer Generator
10/4/2015 © 2015 RTI 13
• The simplest data generator
size_t seed = time(NULL);
srandom(seed);
size_t rand()
{
return random();
}
• Alternatively
size_t seed =
std::chrono::system_clock::now().time_since_epoch().count();
size_t rand()
{
static std::mt19937 mt(seed);
return mt();
}
Fundamental Data Generators
10/4/2015 © 2015 RTI 14
• A bool generator
bool bool_gen() {
return rand() % 2;
}
• An uppercase character generator
char uppercase_gen() // A=65, Z=90
return static_cast<char>(‘A’ + rand() % 26))
}
Data Generators
10/4/2015 © 2015 RTI 15
• A range generator
– Generates any number in the range
int range_gen(int lo, int hi)
return lo + rand() % (hi – lo + 1);
}
• Inconvenient because args must be passed every time
Use state!
Closure as generator
10/4/2015 © 2015 RTI 16
• A stateful range generator
– Generates a random number in the given range
auto make_range_gen(int lo, int hi)
return [lo, hi]() {
return lo + rand() % (hi – lo + 1);
}
}
auto r = range_gen(20, 25);
std::cout << r(); // one of 20, 21, 22, 23, 24, 25
Closure as generator
10/4/2015 © 2015 RTI 17
• The oneof generator
template <class T>
auto make_oneof_gen(std::initializer_list<T> list)
{
return [options = std::vector<T>(list)]() {
return *(options.begin() + rand() % options.size());
};
}
auto days = { “Sun”, “Mon”, “Tue”, “Wed”, “Thu”, “Fri”, “Sat” }
auto gen = make_oneof_gen(days);
std::cout << gen(); // one of Sun, Mon, Tue, Wed, Thu, Fri, Sat
10/4/2015 © 2015 RTI 18
“Closures are poor man's
objects; Objects are poor
man's closure”
-- The venerable master Qc Na
Source Google images
Closure vs Object
• Is function/closure a sufficient abstraction for
any generator?
[]() {
return blah;
}
• Answer depends upon your language
– No. In C++
10/4/2015 © 2015 RTI 19
The Generator Class Template
10/4/2015 © 2015 RTI 20
template <class T, class GenFunc>
struct Gen : private GenFunc
{
typedef T value_type;
explicit Gen(GenFunc func)
: GenFunc(std::move(func))
{ }
T generate()
{
return GenFunc::operator()();
}
auto map(...) const;
auto zip_with(...) const;
auto concat(...) const;
auto take(...) const;auto concat_map(...) const;
auto reduce(...) const;
auto where(...) const;
auto scan(...) const;
};
Creating Gen<T> from lambdas
template <class GenFunc>
auto make_gen_from(GenFunc&& func)
{
return Gen<decltype(func()), GenFunc>
(std::forward<GenFunc>(func));
}
template <class Integer>
auto make_range_gen(Integer lo, Integer hi)
{
return make_gen_from([lo, hi]() {
return static_cast<Integer>(lo + rand() % (hi - lo));
});
}
10/4/2015 © 2015 RTI 21
Composing Generators
• Producing complex Generators from one or
more simpler Generators
10/4/2015 © 2015 RTI 22
Generator
map
reduce
concat
where
zip_with
concat_map
take
scan
Mapping over a generator
10/4/2015 © 2015 RTI 23
vector<string> days = { “Sun”, “Mon”, “Tue”, “Wed”,
“Thu”, “Fri”, “Sat” };
auto range_gen = gen::make_range_gen(0,6);
// random numbers in range 0..6
auto day_gen = range_gen.map([&](int i) { return days[i]; });
// random days in range “Sun” to “Sat”
while(true)
std::cout << day_gen.generate();
// random days in range “Sun” to “Sat”
Gen<int>  Gen<string>
f(int  string)
std::function<string(int)>
10/4/2015 © 2015 RTI 24
Generator is a
You can
over it.
Functor Laws
• Composition Law
gen.map(f).map(g) == gen.map(g o f)
10/4/2015 © 2015 RTI 25
auto DAY_gen = range_gen
.map([&](int i) { return days[i]; });
.map([](const string & str) {
return std::toupper(str, std::locale());
});
auto DAY_gen = range_gen.map([&](int i) {
return std::to_upper(days[i], std::locale());
});
Functor Laws
• Identity Law
gen.map(a -> a) == gen
10/4/2015 © 2015 RTI 26
auto gen2 == gen.map([](auto a) { return a; });
• Both gen and gen2 will generate the same data
– Their identities are different but they are still the same
Implementing map
template <class T>
template <class Func>
auto Gen<T>::map(Func&& func) const
{
return make_gen_from(
[self = *this,
func = std::forward<Func>(func)]() mutable {
return func(self.generate());
});
}
10/4/2015 © 2015 RTI 27
Concatenating generators
10/4/2015 © 2015 RTI 28
vector<string> days = { “Sun”, “Mon”, “Tue”, “Wed”,
“Thu”, “Fri”, “Sat” };
auto day_gen = gen::make_inorder_gen(days)
// Sun,Mon,...,Sat
vector<string> months= { “Jan”, “Feb”, “Mar”, “Apr”,
“May”, “Jun”, “Jul”, “Aug”,
“Sept”, “Oct”, “Nov”, “Dec” };
auto month_gen = gen::make_inorder_gen(months);
auto concat_gen = days_gen.concat(month_gen);
for(int i = 0; i < 19; ++i)
std::cout << concat_gen.generate();
// Sun,Mon,...,Sat,Jan,Feb,Mar,...,Dec
10/4/2015 © 2015 RTI 29
Generator is a
Monoid Laws
• Identity Law
M o id = id o M = M
• Binary operation o = append
• Appending to identity (either way) must yield
the same generator
10/4/2015 © 2015 RTI 30
auto identity = gen::make_empty_gen<int>();
gen::make_inorder_gen({ 1, 2, 3}).append(identity)
==
identity.append(gen::make_inorder_gen({ 1, 2, 3});
Monoid Laws
• Associative Law
(f o g) o h = f o (g o h)
• Binary operation o = append
• Order of operation does not matter. (The order of
operands does)
– Not to be confused with commutative property where the order of
operands does not matter
10/4/2015 © 2015 RTI 31
auto f = gen::make_inorder_gen({ 1, 2});
auto g = gen::make_inorder_gen({ 3, 4});
auto h = gen::make_inorder_gen({ 5, 6});
(f.append(g)).append(h)
==
f.append(g.append(h));
Generator Identity make_empty_gen
template <class T>
auto make_empty_gen()
{
return make_gen_from([]() {
throw std::out_of_range("empty generator!");
return std::declval<T>();
});
}
10/4/2015 © 2015 RTI 32
Zipping Generators
10/4/2015 © 2015 RTI 33
auto x_gen = gen::make_stepper_gen(0,100);
auto y_gen = gen::make_stepper_gen(0,200,2);
auto point_gen =
x_gen.zip_with([](int x, int y)
return std::make_pair(x, y);
}, y_gen);
for(auto _: { 1,2,3 })
std::cout << point_gen.generate(); // {0,0}, {1,2}, {3,4}
end
Implementing zip_with
template <class T>
template <class Zipper, class... GenList>
auto Gen<T>::zip_with(Zipper&& func, GenList&&... genlist) const
{
return make_gen_from(
[self = *this,
genlist...,
func = std::forward<Zipper>(func)]() mutable {
return func(self.generate(), genlist.generate()...);
});
}
10/4/2015 © 2015 RTI 34
10/4/2015 © 2015 RTI 35
Generator is a
Dependent Generators (concat_map)
auto triangle_gen =
gen::make_inorder_gen({1,2,3,4,5,4,3,2,1})
.concat_map([](int i) {
std::cout << "n";
return gen::make_stepper_gen(1, i);
});
try {
while(true)
std::cout << triangle_gen.generate();
}
catch(std::out_of_range &) {
}
10/4/2015 © 2015 RTI 36
1
12
123
1234
12345
1234
123
12
1
Monad Laws
auto f = [](int i) { return gen::make_stepper_gen(1, i); };
auto g = [](int i) { return gen::make_stepper_gen(i, 1, -1); };
auto M = gen::make_single_gen(300);
// left identity
is_same(M.concat_map(f), f(300));
// right identity
is_same(M.concat_map([](int i) {
return gen::make_single_gen(i);
}), M);
// associativity
is_same(M.concat_map(f).concat_map(g),
M.concat_map([f,g](int i) mutable {
return f(i).concat_map(g);
}));
10/4/2015 © 2015 RTI 37
10/4/2015 © 2015 RTI 38
The Mathematics of the Generator API
Generators
• General design principal
– Create a language to solve a problem
– API is the language
– Reuse parsing/compilation of the host language (duh!)
• The “language” of Generators
– Primitive values are basic generators
– Complex values are composite generators
– All APIs result in some generator
• Especially, map, zip, reduce, etc.
– I.e., generators form an algebra
10/4/2015 © 2015 RTI 39
Algebra
A first-class abstraction
+
Compositional* API
10/4/2015 © 2015 RTI 40
*Composition based on mathematical concepts
10/4/2015 © 2015 RTI 41
What Math Concepts?
• Algebraic Structures from Category Theory
–Monoid
–Functor
–Monad
–Applicative
• Where to begin?
–Haskell
–But innocent should start with Scala perhaps
Back to the property-test in RefleX
10/4/2015 © 2015 RTI 42
template <class T>
void test_roundtrip_property(const T & in)
{
reflex::TypeManager<T> tm;
reflex::SafeDynamicData<T> safedd =
tm.create_dynamicdata(in);
reflex::read_dynamicdata(out, safedd);
assert(in == out);
}
What’s the input data?
What are the input types?
10/4/2015 © 2015 RTI 43
if we can generate
we can generate
Random Numbers at Compile-time
#include <stdio.h>
enum test { Foo = RANDOM };
int main(void)
{
enum test foo = Foo;
printf("foo = %dn", foo);
return 0;
}
10/4/2015 © 2015 RTI 44
$ gcc –DRANDOM=$RANDOM main.c –o main
$ ./main
foo = 17695
Random Numbers at Compile-time
#include <stdio.h>
enum test { Foo = RANDOM,
Bar = LFSR(Foo) };
int main(void) {
enum test foo = Foo;
enum test bar = Bar;
printf("foo = %d, bar = %dn", foo, bar);
}
10/4/2015 © 2015 RTI 45
#define LFSR_bit(prev)
(((prev >> 0) ^ (prev >> 2) ^ (prev >> 3) ^ (prev >> 5)) & 1)
#define LFSR(prev)
((prev >> 1) | (LFSR_bit(prev) << 15))
$ gcc –DRANDOM=$RANDOM main.c –o main
$ ./main
foo = 17695, bar = 41615
Could be
constexpr
Linear Feedback Shift Register (LFSR)
• Simple random number generator
• 4 bit Fibonacci LFSR
• Feedback polynomial = X4 + X3 + 1
• Taps 4 and 3
10/4/2015 © 2015 RTI 46Image source: wikipedia
Linear Feedback Shift Register (LFSR)
• Live code feedback polynomial (16 bit)
– X16 + X14 + X13 + X11 + 1
• Taps: 16, 14, 13, and 11
10/4/2015 © 2015 RTI 47Image source: wikipedia
Random Type Generation at Compile-Time
template <int I> struct TypeMap;
template <> struct TypeMap<0> {
typedef int type;
};
template <> struct TypeMap<1> {
typedef char type;
};
template <> struct TypeMap<2> {
typedef float type;
};
template <> struct TypeMap<3> {
typedef double type;
};
10/4/2015 © 2015 RTI 48
Random Type Generation at Compile-Time
#include <boost/core/demangle.hpp>
template <int seed>
struct RandomTuple {
typedef typename TypeMap<LFSR(seed) % 4>::type First;
typedef typename TypeMap<LFSR(LFSR(seed)) % 4>::type Second;
typedef typename TypeMap<LFSR(LFSR(LFSR(seed))) % 4>::type Third;
typedef std::tuple<First, Second, Third> type;
};
10/4/2015 © 2015 RTI 49
$ g++ –DRANDOM=$RANDOM main.cpp –o main
$ ./main
foo = 11660, bar = 5830
tuple = std::tuple<float, double, char>
int main(void) {
auto tuple = RandomTuple<RANDOM>::type();
printf("tuple = %s",
boost::core::demangle(typeid(tuple).name()).c_str());
}
Live code
Tuple Value Generator (zip)
template <class... Args>
struct GenFactory<std::tuple<Args...>>
{
static auto make()
{
return make_zip_gen([](auto&&... args) {
return std::make_tuple(std::forward<decltype(args)>(args)...);
},
GenFactory<Args>::make()...);
}
};
int main(void) {
auto tuple_gen = GenFactory<RandomTuple<RANDOM>::type>::make();
auto tuple = tuple_gen.generate();
}
10/4/2015 © 2015 RTI 50
Type Generators Demystified
• Random seed as command line #define
• Compile-time random numbers using LFSR
• C++ meta-programming for type synthesis
• std::string generator for type names and
member names
• RefleX to map types to typecode and dynamic data
• Source: https://github.com/sutambe/generators
10/4/2015 © 2015 RTI 51
RefleX Property-test Type Generator
• “Good” Numbers
– 31415 (3 nested structs)
– 32415 (51 nested structs)
– 2626 (12 nested structs)
– 10295 (15 nested structs)
– 21525 (41 nested structs)
– 7937 ( 5 nested structs)
– ...
• “Bad” Numbers
– 2152 (test seg-faults) sizeof(tuple) > 2750 KB!
10/4/2015 © 2015 RTI 52
Github: https://github.com/rticommunity/rticonnextdds-reflex/blob/develop/test/generator
10/4/2015 © 2015 RTI 53
Thank You!

Weitere ähnliche Inhalte

Was ist angesagt?

Was ist angesagt? (20)

Introduction to Scala
Introduction to ScalaIntroduction to Scala
Introduction to Scala
 
inheritance c++
inheritance c++inheritance c++
inheritance c++
 
Arrays In Python | Python Array Operations | Edureka
Arrays In Python | Python Array Operations | EdurekaArrays In Python | Python Array Operations | Edureka
Arrays In Python | Python Array Operations | Edureka
 
What is Dictionary In Python? Python Dictionary Tutorial | Edureka
What is Dictionary In Python? Python Dictionary Tutorial | EdurekaWhat is Dictionary In Python? Python Dictionary Tutorial | Edureka
What is Dictionary In Python? Python Dictionary Tutorial | Edureka
 
parameter passing in c#
parameter passing in c#parameter passing in c#
parameter passing in c#
 
Exceptionhandling
ExceptionhandlingExceptionhandling
Exceptionhandling
 
Sum and Product Types - The Fruit Salad & Fruit Snack Example - From F# to Ha...
Sum and Product Types -The Fruit Salad & Fruit Snack Example - From F# to Ha...Sum and Product Types -The Fruit Salad & Fruit Snack Example - From F# to Ha...
Sum and Product Types - The Fruit Salad & Fruit Snack Example - From F# to Ha...
 
Why The Free Monad isn't Free
Why The Free Monad isn't FreeWhy The Free Monad isn't Free
Why The Free Monad isn't Free
 
Java IO
Java IOJava IO
Java IO
 
Lecture 2
Lecture 2Lecture 2
Lecture 2
 
File in C language
File in C languageFile in C language
File in C language
 
20. Object-Oriented Programming Fundamental Principles
20. Object-Oriented Programming Fundamental Principles20. Object-Oriented Programming Fundamental Principles
20. Object-Oriented Programming Fundamental Principles
 
Generics in java
Generics in javaGenerics in java
Generics in java
 
Object oriented approach in python programming
Object oriented approach in python programmingObject oriented approach in python programming
Object oriented approach in python programming
 
String in java
String in javaString in java
String in java
 
Python 101: Python for Absolute Beginners (PyTexas 2014)
Python 101: Python for Absolute Beginners (PyTexas 2014)Python 101: Python for Absolute Beginners (PyTexas 2014)
Python 101: Python for Absolute Beginners (PyTexas 2014)
 
L21 io streams
L21 io streamsL21 io streams
L21 io streams
 
Hash map
Hash mapHash map
Hash map
 
Pipeline oriented programming
Pipeline oriented programmingPipeline oriented programming
Pipeline oriented programming
 
Java Method, Static Block
Java Method, Static BlockJava Method, Static Block
Java Method, Static Block
 

Ähnlich wie C++ Generators and Property-based Testing

Testing of javacript
Testing of javacriptTesting of javacript
Testing of javacript
Lei Kang
 
Toub parallelism tour_oct2009
Toub parallelism tour_oct2009Toub parallelism tour_oct2009
Toub parallelism tour_oct2009
nkaluva
 

Ähnlich wie C++ Generators and Property-based Testing (20)

Systematic Generation Data and Types in C++
Systematic Generation Data and Types in C++Systematic Generation Data and Types in C++
Systematic Generation Data and Types in C++
 
Property-based Testing and Generators (Lua)
Property-based Testing and Generators (Lua)Property-based Testing and Generators (Lua)
Property-based Testing and Generators (Lua)
 
C# 6.0 Preview
C# 6.0 PreviewC# 6.0 Preview
C# 6.0 Preview
 
Eclipse Con 2015: Codan - a C/C++ Code Analysis Framework for CDT
Eclipse Con 2015: Codan - a C/C++ Code Analysis Framework for CDTEclipse Con 2015: Codan - a C/C++ Code Analysis Framework for CDT
Eclipse Con 2015: Codan - a C/C++ Code Analysis Framework for CDT
 
Testing of javacript
Testing of javacriptTesting of javacript
Testing of javacript
 
Golang dot-testing-lite
Golang dot-testing-liteGolang dot-testing-lite
Golang dot-testing-lite
 
Function
FunctionFunction
Function
 
Test strategies for data processing pipelines, v2.0
Test strategies for data processing pipelines, v2.0Test strategies for data processing pipelines, v2.0
Test strategies for data processing pipelines, v2.0
 
The real beginner's guide to android testing
The real beginner's guide to android testingThe real beginner's guide to android testing
The real beginner's guide to android testing
 
RxJava on Android
RxJava on AndroidRxJava on Android
RxJava on Android
 
Tech talks annual 2015 kirk pepperdine_ripping apart java 8 streams
Tech talks annual 2015 kirk pepperdine_ripping apart java 8 streamsTech talks annual 2015 kirk pepperdine_ripping apart java 8 streams
Tech talks annual 2015 kirk pepperdine_ripping apart java 8 streams
 
GlobalLogic Test Automation Online TechTalk “Test Driven Development as a Per...
GlobalLogic Test Automation Online TechTalk “Test Driven Development as a Per...GlobalLogic Test Automation Online TechTalk “Test Driven Development as a Per...
GlobalLogic Test Automation Online TechTalk “Test Driven Development as a Per...
 
2010 07-28-testing-zf-apps
2010 07-28-testing-zf-apps2010 07-28-testing-zf-apps
2010 07-28-testing-zf-apps
 
Toub parallelism tour_oct2009
Toub parallelism tour_oct2009Toub parallelism tour_oct2009
Toub parallelism tour_oct2009
 
Advanced Analytics using Apache Hive
Advanced Analytics using Apache HiveAdvanced Analytics using Apache Hive
Advanced Analytics using Apache Hive
 
Applying Compiler Techniques to Iterate At Blazing Speed
Applying Compiler Techniques to Iterate At Blazing SpeedApplying Compiler Techniques to Iterate At Blazing Speed
Applying Compiler Techniques to Iterate At Blazing Speed
 
Automated Developer Testing: Achievements and Challenges
Automated Developer Testing: Achievements and ChallengesAutomated Developer Testing: Achievements and Challenges
Automated Developer Testing: Achievements and Challenges
 
Groovy Introduction - JAX Germany - 2008
Groovy Introduction - JAX Germany - 2008Groovy Introduction - JAX Germany - 2008
Groovy Introduction - JAX Germany - 2008
 
Javascript
JavascriptJavascript
Javascript
 
Lo Mejor Del Pdc2008 El Futrode C#
Lo Mejor Del Pdc2008 El Futrode C#Lo Mejor Del Pdc2008 El Futrode C#
Lo Mejor Del Pdc2008 El Futrode C#
 

Mehr von Sumant Tambe

Reactive Stream Processing for Data-centric Publish/Subscribe
Reactive Stream Processing for Data-centric Publish/SubscribeReactive Stream Processing for Data-centric Publish/Subscribe
Reactive Stream Processing for Data-centric Publish/Subscribe
Sumant Tambe
 
An Extensible Architecture for Avionics Sensor Health Assessment Using DDS
An Extensible Architecture for Avionics Sensor Health Assessment Using DDSAn Extensible Architecture for Avionics Sensor Health Assessment Using DDS
An Extensible Architecture for Avionics Sensor Health Assessment Using DDS
Sumant Tambe
 
Standardizing the Data Distribution Service (DDS) API for Modern C++
Standardizing the Data Distribution Service (DDS) API for Modern C++Standardizing the Data Distribution Service (DDS) API for Modern C++
Standardizing the Data Distribution Service (DDS) API for Modern C++
Sumant Tambe
 

Mehr von Sumant Tambe (19)

Kafka tiered-storage-meetup-2022-final-presented
Kafka tiered-storage-meetup-2022-final-presentedKafka tiered-storage-meetup-2022-final-presented
Kafka tiered-storage-meetup-2022-final-presented
 
Tuning kafka pipelines
Tuning kafka pipelinesTuning kafka pipelines
Tuning kafka pipelines
 
New Tools for a More Functional C++
New Tools for a More Functional C++New Tools for a More Functional C++
New Tools for a More Functional C++
 
C++ Coroutines
C++ CoroutinesC++ Coroutines
C++ Coroutines
 
Reactive Stream Processing in Industrial IoT using DDS and Rx
Reactive Stream Processing in Industrial IoT using DDS and RxReactive Stream Processing in Industrial IoT using DDS and Rx
Reactive Stream Processing in Industrial IoT using DDS and Rx
 
RPC over DDS Beta 1
RPC over DDS Beta 1RPC over DDS Beta 1
RPC over DDS Beta 1
 
Remote Log Analytics Using DDS, ELK, and RxJS
Remote Log Analytics Using DDS, ELK, and RxJSRemote Log Analytics Using DDS, ELK, and RxJS
Remote Log Analytics Using DDS, ELK, and RxJS
 
Reactive Stream Processing for Data-centric Publish/Subscribe
Reactive Stream Processing for Data-centric Publish/SubscribeReactive Stream Processing for Data-centric Publish/Subscribe
Reactive Stream Processing for Data-centric Publish/Subscribe
 
Reactive Stream Processing Using DDS and Rx
Reactive Stream Processing Using DDS and RxReactive Stream Processing Using DDS and Rx
Reactive Stream Processing Using DDS and Rx
 
Fun with Lambdas: C++14 Style (part 2)
Fun with Lambdas: C++14 Style (part 2)Fun with Lambdas: C++14 Style (part 2)
Fun with Lambdas: C++14 Style (part 2)
 
Fun with Lambdas: C++14 Style (part 1)
Fun with Lambdas: C++14 Style (part 1)Fun with Lambdas: C++14 Style (part 1)
Fun with Lambdas: C++14 Style (part 1)
 
An Extensible Architecture for Avionics Sensor Health Assessment Using DDS
An Extensible Architecture for Avionics Sensor Health Assessment Using DDSAn Extensible Architecture for Avionics Sensor Health Assessment Using DDS
An Extensible Architecture for Avionics Sensor Health Assessment Using DDS
 
Overloading in Overdrive: A Generic Data-Centric Messaging Library for DDS
Overloading in Overdrive: A Generic Data-Centric Messaging Library for DDSOverloading in Overdrive: A Generic Data-Centric Messaging Library for DDS
Overloading in Overdrive: A Generic Data-Centric Messaging Library for DDS
 
Standardizing the Data Distribution Service (DDS) API for Modern C++
Standardizing the Data Distribution Service (DDS) API for Modern C++Standardizing the Data Distribution Service (DDS) API for Modern C++
Standardizing the Data Distribution Service (DDS) API for Modern C++
 
Communication Patterns Using Data-Centric Publish/Subscribe
Communication Patterns Using Data-Centric Publish/SubscribeCommunication Patterns Using Data-Centric Publish/Subscribe
Communication Patterns Using Data-Centric Publish/Subscribe
 
C++11 Idioms @ Silicon Valley Code Camp 2012
C++11 Idioms @ Silicon Valley Code Camp 2012 C++11 Idioms @ Silicon Valley Code Camp 2012
C++11 Idioms @ Silicon Valley Code Camp 2012
 
Retargeting Embedded Software Stack for Many-Core Systems
Retargeting Embedded Software Stack for Many-Core SystemsRetargeting Embedded Software Stack for Many-Core Systems
Retargeting Embedded Software Stack for Many-Core Systems
 
Ph.D. Dissertation
Ph.D. DissertationPh.D. Dissertation
Ph.D. Dissertation
 
Native XML processing in C++ (BoostCon'11)
Native XML processing in C++ (BoostCon'11)Native XML processing in C++ (BoostCon'11)
Native XML processing in C++ (BoostCon'11)
 

Kürzlich hochgeladen

+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...
+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...
+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...
?#DUbAI#??##{{(☎️+971_581248768%)**%*]'#abortion pills for sale in dubai@
 

Kürzlich hochgeladen (20)

MS Copilot expands with MS Graph connectors
MS Copilot expands with MS Graph connectorsMS Copilot expands with MS Graph connectors
MS Copilot expands with MS Graph connectors
 
Connector Corner: Accelerate revenue generation using UiPath API-centric busi...
Connector Corner: Accelerate revenue generation using UiPath API-centric busi...Connector Corner: Accelerate revenue generation using UiPath API-centric busi...
Connector Corner: Accelerate revenue generation using UiPath API-centric busi...
 
A Year of the Servo Reboot: Where Are We Now?
A Year of the Servo Reboot: Where Are We Now?A Year of the Servo Reboot: Where Are We Now?
A Year of the Servo Reboot: Where Are We Now?
 
Polkadot JAM Slides - Token2049 - By Dr. Gavin Wood
Polkadot JAM Slides - Token2049 - By Dr. Gavin WoodPolkadot JAM Slides - Token2049 - By Dr. Gavin Wood
Polkadot JAM Slides - Token2049 - By Dr. Gavin Wood
 
2024: Domino Containers - The Next Step. News from the Domino Container commu...
2024: Domino Containers - The Next Step. News from the Domino Container commu...2024: Domino Containers - The Next Step. News from the Domino Container commu...
2024: Domino Containers - The Next Step. News from the Domino Container commu...
 
GenAI Risks & Security Meetup 01052024.pdf
GenAI Risks & Security Meetup 01052024.pdfGenAI Risks & Security Meetup 01052024.pdf
GenAI Risks & Security Meetup 01052024.pdf
 
Apidays New York 2024 - The Good, the Bad and the Governed by David O'Neill, ...
Apidays New York 2024 - The Good, the Bad and the Governed by David O'Neill, ...Apidays New York 2024 - The Good, the Bad and the Governed by David O'Neill, ...
Apidays New York 2024 - The Good, the Bad and the Governed by David O'Neill, ...
 
Emergent Methods: Multi-lingual narrative tracking in the news - real-time ex...
Emergent Methods: Multi-lingual narrative tracking in the news - real-time ex...Emergent Methods: Multi-lingual narrative tracking in the news - real-time ex...
Emergent Methods: Multi-lingual narrative tracking in the news - real-time ex...
 
"I see eyes in my soup": How Delivery Hero implemented the safety system for ...
"I see eyes in my soup": How Delivery Hero implemented the safety system for ..."I see eyes in my soup": How Delivery Hero implemented the safety system for ...
"I see eyes in my soup": How Delivery Hero implemented the safety system for ...
 
MINDCTI Revenue Release Quarter One 2024
MINDCTI Revenue Release Quarter One 2024MINDCTI Revenue Release Quarter One 2024
MINDCTI Revenue Release Quarter One 2024
 
Boost Fertility New Invention Ups Success Rates.pdf
Boost Fertility New Invention Ups Success Rates.pdfBoost Fertility New Invention Ups Success Rates.pdf
Boost Fertility New Invention Ups Success Rates.pdf
 
TrustArc Webinar - Stay Ahead of US State Data Privacy Law Developments
TrustArc Webinar - Stay Ahead of US State Data Privacy Law DevelopmentsTrustArc Webinar - Stay Ahead of US State Data Privacy Law Developments
TrustArc Webinar - Stay Ahead of US State Data Privacy Law Developments
 
AXA XL - Insurer Innovation Award Americas 2024
AXA XL - Insurer Innovation Award Americas 2024AXA XL - Insurer Innovation Award Americas 2024
AXA XL - Insurer Innovation Award Americas 2024
 
Manulife - Insurer Transformation Award 2024
Manulife - Insurer Transformation Award 2024Manulife - Insurer Transformation Award 2024
Manulife - Insurer Transformation Award 2024
 
ProductAnonymous-April2024-WinProductDiscovery-MelissaKlemke
ProductAnonymous-April2024-WinProductDiscovery-MelissaKlemkeProductAnonymous-April2024-WinProductDiscovery-MelissaKlemke
ProductAnonymous-April2024-WinProductDiscovery-MelissaKlemke
 
AWS Community Day CPH - Three problems of Terraform
AWS Community Day CPH - Three problems of TerraformAWS Community Day CPH - Three problems of Terraform
AWS Community Day CPH - Three problems of Terraform
 
Web Form Automation for Bonterra Impact Management (fka Social Solutions Apri...
Web Form Automation for Bonterra Impact Management (fka Social Solutions Apri...Web Form Automation for Bonterra Impact Management (fka Social Solutions Apri...
Web Form Automation for Bonterra Impact Management (fka Social Solutions Apri...
 
+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...
+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...
+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...
 
Strategize a Smooth Tenant-to-tenant Migration and Copilot Takeoff
Strategize a Smooth Tenant-to-tenant Migration and Copilot TakeoffStrategize a Smooth Tenant-to-tenant Migration and Copilot Takeoff
Strategize a Smooth Tenant-to-tenant Migration and Copilot Takeoff
 
ICT role in 21st century education and its challenges
ICT role in 21st century education and its challengesICT role in 21st century education and its challenges
ICT role in 21st century education and its challenges
 

C++ Generators and Property-based Testing

  • 1. Your systems. Working as one. Sumant Tambe, PhD Principal Research Engineer and Microsoft VC++ MVP Real-Time Innovations, Inc. @sutambe Oct. 3, 2015
  • 2. 10/4/2015 © 2015 RTI 2 LEESA 2008 Rx4DDS 2014 RefleX 2015 Alternative Title
  • 3. 10/4/2015 © 2015 RTI 3 Author Blogger Open-Source LEESA (C++) Rx4DDS (C++11, C#, JavaScript) (C++11)
  • 4. Why should you care? • If you write software for living and if you are serious about any of the following – Bug-free, Expressive code – Productivity • Modularity • Reusability • Extensibility • Maintainability – Performance/latency • Multi-core scalability – and having fun while doing that! 10/4/2015 © 2015 RTI 4
  • 5. Agenda • Property-based Testing • The need for composable generators • Design/Implementation of the generator library • Mathematics of API design – Functor, Monoid, and Monad • Generators at compile-time (type generators) 10/4/2015 © 2015 RTI 5
  • 6. What’s a Property • Reversing a linked-list twice has no effect – reverse(reverse(list)) == list • Compression can make things smaller – compress(input).size <= input.size • Round-trip serialization/deserialization has no effect – deserialize(serialize(input)) == input 10/4/2015 © 2015 RTI 6
  • 7. Testing RefleX • RefleX is short for Reflection for DDS-Xtypes • Serialization and Deserialization – Serializes types and data – Works off of C++ struct/classes directly • C++11/14 • Link 10/4/2015 © 2015 RTI 7
  • 8. RefleX Example 10/4/2015 © 2015 RTI 8 class ShapeType { std::string color_; int x_, y_, shapesize_; public: ShapeType() {} ShapeType(const std::string & color, int x, int y, int shapesize) : color_(color), x_(x), y_(y), shapesize_(shapesize) {} std::string & color(); int & x(); int & y(); int & shapesize(); }; #include "reflex.h" REFLEX_ADAPT_STRUCT( ShapeType, (std::string, color(), KEY) (int, x()) (int, y()) (int, shapesize()))
  • 9. A property-test in RefleX 10/4/2015 © 2015 RTI 9 template <class T> void test_roundtrip_property(const T & in) { reflex::TypeManager<T> tm; reflex::SafeDynamicData<T> safedd = tm.create_dynamicdata(in); reflex::read_dynamicdata(out, safedd); assert(in == out); }
  • 10. Property-based Testing • Complementary to traditional example-based testing • Specify post-conditions that must hold no matter what • Encourages the programmer to think harder about the code • More declarative • Need data generators to produce inputs • Free reproducers! – Good property-based testing frameworks shrink inputs to minimal automatically • Famous: Haskell’s QuickCheck, Scala’s ScalaTest 10/4/2015 © 2015 RTI 10
  • 11. A property-test in RefleX 10/4/2015 © 2015 RTI 11 template <class T> void test_roundtrip_property(const T & in) { reflex::TypeManager<T> tm; reflex::SafeDynamicData<T> safedd = tm.create_dynamicdata(in); reflex::read_dynamicdata(out, safedd); assert(in == out); } What’s the input data? What are the input types?
  • 13. Random Integer Generator 10/4/2015 © 2015 RTI 13 • The simplest data generator size_t seed = time(NULL); srandom(seed); size_t rand() { return random(); } • Alternatively size_t seed = std::chrono::system_clock::now().time_since_epoch().count(); size_t rand() { static std::mt19937 mt(seed); return mt(); }
  • 14. Fundamental Data Generators 10/4/2015 © 2015 RTI 14 • A bool generator bool bool_gen() { return rand() % 2; } • An uppercase character generator char uppercase_gen() // A=65, Z=90 return static_cast<char>(‘A’ + rand() % 26)) }
  • 15. Data Generators 10/4/2015 © 2015 RTI 15 • A range generator – Generates any number in the range int range_gen(int lo, int hi) return lo + rand() % (hi – lo + 1); } • Inconvenient because args must be passed every time Use state!
  • 16. Closure as generator 10/4/2015 © 2015 RTI 16 • A stateful range generator – Generates a random number in the given range auto make_range_gen(int lo, int hi) return [lo, hi]() { return lo + rand() % (hi – lo + 1); } } auto r = range_gen(20, 25); std::cout << r(); // one of 20, 21, 22, 23, 24, 25
  • 17. Closure as generator 10/4/2015 © 2015 RTI 17 • The oneof generator template <class T> auto make_oneof_gen(std::initializer_list<T> list) { return [options = std::vector<T>(list)]() { return *(options.begin() + rand() % options.size()); }; } auto days = { “Sun”, “Mon”, “Tue”, “Wed”, “Thu”, “Fri”, “Sat” } auto gen = make_oneof_gen(days); std::cout << gen(); // one of Sun, Mon, Tue, Wed, Thu, Fri, Sat
  • 18. 10/4/2015 © 2015 RTI 18 “Closures are poor man's objects; Objects are poor man's closure” -- The venerable master Qc Na Source Google images
  • 19. Closure vs Object • Is function/closure a sufficient abstraction for any generator? []() { return blah; } • Answer depends upon your language – No. In C++ 10/4/2015 © 2015 RTI 19
  • 20. The Generator Class Template 10/4/2015 © 2015 RTI 20 template <class T, class GenFunc> struct Gen : private GenFunc { typedef T value_type; explicit Gen(GenFunc func) : GenFunc(std::move(func)) { } T generate() { return GenFunc::operator()(); } auto map(...) const; auto zip_with(...) const; auto concat(...) const; auto take(...) const;auto concat_map(...) const; auto reduce(...) const; auto where(...) const; auto scan(...) const; };
  • 21. Creating Gen<T> from lambdas template <class GenFunc> auto make_gen_from(GenFunc&& func) { return Gen<decltype(func()), GenFunc> (std::forward<GenFunc>(func)); } template <class Integer> auto make_range_gen(Integer lo, Integer hi) { return make_gen_from([lo, hi]() { return static_cast<Integer>(lo + rand() % (hi - lo)); }); } 10/4/2015 © 2015 RTI 21
  • 22. Composing Generators • Producing complex Generators from one or more simpler Generators 10/4/2015 © 2015 RTI 22 Generator map reduce concat where zip_with concat_map take scan
  • 23. Mapping over a generator 10/4/2015 © 2015 RTI 23 vector<string> days = { “Sun”, “Mon”, “Tue”, “Wed”, “Thu”, “Fri”, “Sat” }; auto range_gen = gen::make_range_gen(0,6); // random numbers in range 0..6 auto day_gen = range_gen.map([&](int i) { return days[i]; }); // random days in range “Sun” to “Sat” while(true) std::cout << day_gen.generate(); // random days in range “Sun” to “Sat” Gen<int>  Gen<string> f(int  string) std::function<string(int)>
  • 24. 10/4/2015 © 2015 RTI 24 Generator is a You can over it.
  • 25. Functor Laws • Composition Law gen.map(f).map(g) == gen.map(g o f) 10/4/2015 © 2015 RTI 25 auto DAY_gen = range_gen .map([&](int i) { return days[i]; }); .map([](const string & str) { return std::toupper(str, std::locale()); }); auto DAY_gen = range_gen.map([&](int i) { return std::to_upper(days[i], std::locale()); });
  • 26. Functor Laws • Identity Law gen.map(a -> a) == gen 10/4/2015 © 2015 RTI 26 auto gen2 == gen.map([](auto a) { return a; }); • Both gen and gen2 will generate the same data – Their identities are different but they are still the same
  • 27. Implementing map template <class T> template <class Func> auto Gen<T>::map(Func&& func) const { return make_gen_from( [self = *this, func = std::forward<Func>(func)]() mutable { return func(self.generate()); }); } 10/4/2015 © 2015 RTI 27
  • 28. Concatenating generators 10/4/2015 © 2015 RTI 28 vector<string> days = { “Sun”, “Mon”, “Tue”, “Wed”, “Thu”, “Fri”, “Sat” }; auto day_gen = gen::make_inorder_gen(days) // Sun,Mon,...,Sat vector<string> months= { “Jan”, “Feb”, “Mar”, “Apr”, “May”, “Jun”, “Jul”, “Aug”, “Sept”, “Oct”, “Nov”, “Dec” }; auto month_gen = gen::make_inorder_gen(months); auto concat_gen = days_gen.concat(month_gen); for(int i = 0; i < 19; ++i) std::cout << concat_gen.generate(); // Sun,Mon,...,Sat,Jan,Feb,Mar,...,Dec
  • 29. 10/4/2015 © 2015 RTI 29 Generator is a
  • 30. Monoid Laws • Identity Law M o id = id o M = M • Binary operation o = append • Appending to identity (either way) must yield the same generator 10/4/2015 © 2015 RTI 30 auto identity = gen::make_empty_gen<int>(); gen::make_inorder_gen({ 1, 2, 3}).append(identity) == identity.append(gen::make_inorder_gen({ 1, 2, 3});
  • 31. Monoid Laws • Associative Law (f o g) o h = f o (g o h) • Binary operation o = append • Order of operation does not matter. (The order of operands does) – Not to be confused with commutative property where the order of operands does not matter 10/4/2015 © 2015 RTI 31 auto f = gen::make_inorder_gen({ 1, 2}); auto g = gen::make_inorder_gen({ 3, 4}); auto h = gen::make_inorder_gen({ 5, 6}); (f.append(g)).append(h) == f.append(g.append(h));
  • 32. Generator Identity make_empty_gen template <class T> auto make_empty_gen() { return make_gen_from([]() { throw std::out_of_range("empty generator!"); return std::declval<T>(); }); } 10/4/2015 © 2015 RTI 32
  • 33. Zipping Generators 10/4/2015 © 2015 RTI 33 auto x_gen = gen::make_stepper_gen(0,100); auto y_gen = gen::make_stepper_gen(0,200,2); auto point_gen = x_gen.zip_with([](int x, int y) return std::make_pair(x, y); }, y_gen); for(auto _: { 1,2,3 }) std::cout << point_gen.generate(); // {0,0}, {1,2}, {3,4} end
  • 34. Implementing zip_with template <class T> template <class Zipper, class... GenList> auto Gen<T>::zip_with(Zipper&& func, GenList&&... genlist) const { return make_gen_from( [self = *this, genlist..., func = std::forward<Zipper>(func)]() mutable { return func(self.generate(), genlist.generate()...); }); } 10/4/2015 © 2015 RTI 34
  • 35. 10/4/2015 © 2015 RTI 35 Generator is a
  • 36. Dependent Generators (concat_map) auto triangle_gen = gen::make_inorder_gen({1,2,3,4,5,4,3,2,1}) .concat_map([](int i) { std::cout << "n"; return gen::make_stepper_gen(1, i); }); try { while(true) std::cout << triangle_gen.generate(); } catch(std::out_of_range &) { } 10/4/2015 © 2015 RTI 36 1 12 123 1234 12345 1234 123 12 1
  • 37. Monad Laws auto f = [](int i) { return gen::make_stepper_gen(1, i); }; auto g = [](int i) { return gen::make_stepper_gen(i, 1, -1); }; auto M = gen::make_single_gen(300); // left identity is_same(M.concat_map(f), f(300)); // right identity is_same(M.concat_map([](int i) { return gen::make_single_gen(i); }), M); // associativity is_same(M.concat_map(f).concat_map(g), M.concat_map([f,g](int i) mutable { return f(i).concat_map(g); })); 10/4/2015 © 2015 RTI 37
  • 38. 10/4/2015 © 2015 RTI 38 The Mathematics of the Generator API
  • 39. Generators • General design principal – Create a language to solve a problem – API is the language – Reuse parsing/compilation of the host language (duh!) • The “language” of Generators – Primitive values are basic generators – Complex values are composite generators – All APIs result in some generator • Especially, map, zip, reduce, etc. – I.e., generators form an algebra 10/4/2015 © 2015 RTI 39
  • 40. Algebra A first-class abstraction + Compositional* API 10/4/2015 © 2015 RTI 40 *Composition based on mathematical concepts
  • 41. 10/4/2015 © 2015 RTI 41 What Math Concepts? • Algebraic Structures from Category Theory –Monoid –Functor –Monad –Applicative • Where to begin? –Haskell –But innocent should start with Scala perhaps
  • 42. Back to the property-test in RefleX 10/4/2015 © 2015 RTI 42 template <class T> void test_roundtrip_property(const T & in) { reflex::TypeManager<T> tm; reflex::SafeDynamicData<T> safedd = tm.create_dynamicdata(in); reflex::read_dynamicdata(out, safedd); assert(in == out); } What’s the input data? What are the input types?
  • 43. 10/4/2015 © 2015 RTI 43 if we can generate we can generate
  • 44. Random Numbers at Compile-time #include <stdio.h> enum test { Foo = RANDOM }; int main(void) { enum test foo = Foo; printf("foo = %dn", foo); return 0; } 10/4/2015 © 2015 RTI 44 $ gcc –DRANDOM=$RANDOM main.c –o main $ ./main foo = 17695
  • 45. Random Numbers at Compile-time #include <stdio.h> enum test { Foo = RANDOM, Bar = LFSR(Foo) }; int main(void) { enum test foo = Foo; enum test bar = Bar; printf("foo = %d, bar = %dn", foo, bar); } 10/4/2015 © 2015 RTI 45 #define LFSR_bit(prev) (((prev >> 0) ^ (prev >> 2) ^ (prev >> 3) ^ (prev >> 5)) & 1) #define LFSR(prev) ((prev >> 1) | (LFSR_bit(prev) << 15)) $ gcc –DRANDOM=$RANDOM main.c –o main $ ./main foo = 17695, bar = 41615 Could be constexpr
  • 46. Linear Feedback Shift Register (LFSR) • Simple random number generator • 4 bit Fibonacci LFSR • Feedback polynomial = X4 + X3 + 1 • Taps 4 and 3 10/4/2015 © 2015 RTI 46Image source: wikipedia
  • 47. Linear Feedback Shift Register (LFSR) • Live code feedback polynomial (16 bit) – X16 + X14 + X13 + X11 + 1 • Taps: 16, 14, 13, and 11 10/4/2015 © 2015 RTI 47Image source: wikipedia
  • 48. Random Type Generation at Compile-Time template <int I> struct TypeMap; template <> struct TypeMap<0> { typedef int type; }; template <> struct TypeMap<1> { typedef char type; }; template <> struct TypeMap<2> { typedef float type; }; template <> struct TypeMap<3> { typedef double type; }; 10/4/2015 © 2015 RTI 48
  • 49. Random Type Generation at Compile-Time #include <boost/core/demangle.hpp> template <int seed> struct RandomTuple { typedef typename TypeMap<LFSR(seed) % 4>::type First; typedef typename TypeMap<LFSR(LFSR(seed)) % 4>::type Second; typedef typename TypeMap<LFSR(LFSR(LFSR(seed))) % 4>::type Third; typedef std::tuple<First, Second, Third> type; }; 10/4/2015 © 2015 RTI 49 $ g++ –DRANDOM=$RANDOM main.cpp –o main $ ./main foo = 11660, bar = 5830 tuple = std::tuple<float, double, char> int main(void) { auto tuple = RandomTuple<RANDOM>::type(); printf("tuple = %s", boost::core::demangle(typeid(tuple).name()).c_str()); } Live code
  • 50. Tuple Value Generator (zip) template <class... Args> struct GenFactory<std::tuple<Args...>> { static auto make() { return make_zip_gen([](auto&&... args) { return std::make_tuple(std::forward<decltype(args)>(args)...); }, GenFactory<Args>::make()...); } }; int main(void) { auto tuple_gen = GenFactory<RandomTuple<RANDOM>::type>::make(); auto tuple = tuple_gen.generate(); } 10/4/2015 © 2015 RTI 50
  • 51. Type Generators Demystified • Random seed as command line #define • Compile-time random numbers using LFSR • C++ meta-programming for type synthesis • std::string generator for type names and member names • RefleX to map types to typecode and dynamic data • Source: https://github.com/sutambe/generators 10/4/2015 © 2015 RTI 51
  • 52. RefleX Property-test Type Generator • “Good” Numbers – 31415 (3 nested structs) – 32415 (51 nested structs) – 2626 (12 nested structs) – 10295 (15 nested structs) – 21525 (41 nested structs) – 7937 ( 5 nested structs) – ... • “Bad” Numbers – 2152 (test seg-faults) sizeof(tuple) > 2750 KB! 10/4/2015 © 2015 RTI 52 Github: https://github.com/rticommunity/rticonnextdds-reflex/blob/develop/test/generator
  • 53. 10/4/2015 © 2015 RTI 53 Thank You!

Hinweis der Redaktion

  1. Incompressible strings of every length exist.