Improved output of stress test stat
[libcds.git] / test / include / cds_test / stress_test.h
1 /*
2     This file is a part of libcds - Concurrent Data Structures library
3
4     (C) Copyright Maxim Khizhinsky (libcds.dev@gmail.com) 2006-2016
5
6     Source code repo: http://github.com/khizmax/libcds/
7     Download: http://sourceforge.net/projects/libcds/files/
8
9     Redistribution and use in source and binary forms, with or without
10     modification, are permitted provided that the following conditions are met:
11
12     * Redistributions of source code must retain the above copyright notice, this
13     list of conditions and the following disclaimer.
14
15     * Redistributions in binary form must reproduce the above copyright notice,
16     this list of conditions and the following disclaimer in the documentation
17     and/or other materials provided with the distribution.
18
19     THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
20     AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21     IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
22     DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
23     FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24     DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
25     SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
26     CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
27     OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28     OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 */
30
31 #ifndef CDSTEST_STRESS_TEST_H
32 #define CDSTEST_STRESS_TEST_H
33
34 #include <map>
35 #include <cds_test/fixture.h>
36 #include <cds_test/thread.h>
37
38 namespace cds_test {
39
40     // Test configuration
41     class config
42     {
43     public:
44         std::string get( const char * pszParamName, const char * pszDefVal = NULL ) const
45         {
46             std::string strParamName( pszParamName );
47             auto it = m_Cfg.find( strParamName );
48             if ( it == m_Cfg.end())
49                 return std::string( pszDefVal ); // param not found -> returns default value
50             return it->second;
51         }
52
53         int get_int( const char * pszParamName, int defVal = 0 ) const
54         {
55             std::string strParamName( pszParamName );
56             cfg_map::const_iterator it = m_Cfg.find( strParamName );
57             if ( it == m_Cfg.end())
58                 return defVal; // param not found -> returns default value
59             return atoi( it->second.c_str());
60         }
61
62         unsigned int get_uint( const char * pszParamName, unsigned int defVal = 0 ) const
63         {
64             std::string strParamName( pszParamName );
65             cfg_map::const_iterator it = m_Cfg.find( strParamName );
66             if ( it == m_Cfg.end())
67                 return defVal; // param not found -> returns default value
68             return static_cast<unsigned int>( strtoul( it->second.c_str(), NULL, 10 ));
69         }
70
71         long get_long( const char * pszParamName, long defVal = 0 ) const
72         {
73             std::string strParamName( pszParamName );
74             cfg_map::const_iterator it = m_Cfg.find( strParamName );
75             if ( it == m_Cfg.end())
76                 return defVal; // param not found -> returns default value
77             return strtol( it->second.c_str(), NULL, 10 );
78         }
79
80         unsigned long get_ulong( const char * pszParamName, unsigned long defVal = 0 ) const
81         {
82             std::string strParamName( pszParamName );
83             cfg_map::const_iterator it = m_Cfg.find( strParamName );
84             if ( it == m_Cfg.end())
85                 return defVal; // param not found -> returns default value
86             return strtoul( it->second.c_str(), NULL, 10 );
87         }
88
89         size_t get_size_t( const char * pszParamName, size_t defVal = 0 ) const
90         {
91             std::string strParamName( pszParamName );
92             cfg_map::const_iterator it = m_Cfg.find( strParamName );
93             if ( it == m_Cfg.end())
94                 return defVal; // param not found -> returns default value
95             return static_cast<size_t>( strtoul( it->second.c_str(), NULL, 10 ));
96         }
97
98         bool get_bool( const char * pszParamName, bool defVal = false ) const
99         {
100             std::string strParamName( pszParamName );
101             cfg_map::const_iterator it = m_Cfg.find( strParamName );
102             if ( it == m_Cfg.end())
103                 return defVal; // param not found -> returns default value
104             return !( it->second.empty()
105                    || it->second == "0"
106                    || it->second == "false"
107                    || it->second == "no"
108                    );
109         }
110
111     private:
112         typedef std::map< std::string, std::string >  cfg_map;
113         cfg_map m_Cfg; // map param_name => value
114
115         friend class config_file;
116     };
117
118     class property_stream
119     {
120     public:
121         static std::string const& stat_prefix();
122         static void set_stat_prefix( char const* prefix );
123     };
124
125     struct stat_prefix
126     {
127         char const* prefix_;
128
129         stat_prefix()
130             : prefix_( nullptr )
131         {}
132
133         stat_prefix( char const* prefix )
134             : prefix_( prefix )
135         {}
136     };
137
138     static inline property_stream& operator<<( property_stream& s, stat_prefix&& prefix )
139     {
140         s.set_stat_prefix( prefix.prefix_ );
141         return s;
142     }
143
144     template <typename T>
145     static inline property_stream& operator <<( property_stream& s, std::pair<char const*, T > prop )
146     {
147         std::stringstream ss;
148         ss << prop.second;
149         ::testing::Test::RecordProperty( prop.first, ss.str().c_str());
150         return s;
151     }
152
153     template <typename T>
154     static inline property_stream& operator <<( property_stream& s, std::pair<std::string, T > prop )
155     {
156         std::stringstream ss;
157         ss << prop.second;
158         ::testing::Test::RecordProperty( prop.first.c_str(), ss.str().c_str());
159         return s;
160     }
161
162     static inline property_stream& operator <<( property_stream& s, std::pair<char const*, std::chrono::milliseconds > prop )
163     {
164         std::stringstream ss;
165         ss << prop.second.count();
166         ::testing::Test::RecordProperty( prop.first, ss.str().c_str());
167         return s;
168     }
169
170 #define CDSSTRESS_STAT_OUT_( name, val ) std::make_pair( name, val )
171 #define CDSSTRESS_STAT_OUT( s, field ) CDSSTRESS_STAT_OUT_( property_stream::stat_prefix() + "." #field, s.field.get())
172
173     class stress_fixture : public fixture
174     {
175     protected:
176         stress_fixture()
177             : m_thread_pool( *this )
178         {}
179
180         //static void SetUpTestCase();
181         //static void TearDownTestCase();
182
183         thread_pool& get_pool()
184         {
185             return m_thread_pool;
186         }
187
188         static property_stream& propout();
189
190     public:
191         static config const& get_config( char const * slot );
192         static config const& get_config( std::string const& slot );
193
194         static std::vector<std::string> load_dictionary();
195
196         static void init_detail_level( int argc, char **argv );
197         static bool check_detail_level( int nLevel );
198
199     private:
200         thread_pool     m_thread_pool;
201     };
202
203
204     // Internal functions
205     void init_config( int argc, char **argv );
206
207 } // namespace cds_test
208
209 #endif // CDSTEST_FIXTURE_H