007cb95968670fddc3bc6f8c09a88267f01cbc67
[ric-plt/sdl.git] / src / cli / testgetsetcommand.cpp
1 #include <ostream>
2 #include <cstdlib>
3 #include <fstream>
4 #include <string>
5 #include <iostream>
6 #include <boost/property_tree/ptree.hpp>
7 #include <boost/property_tree/json_parser.hpp>
8 #include <chrono>
9 #include <thread>
10 #include "private/cli/commandmap.hpp"
11 #include "private/configurationpaths.hpp"
12 #include <sdl/syncstorage.hpp>
13
14 using namespace shareddatalayer;
15 using namespace shareddatalayer::cli;
16
17 namespace
18 {
19     std::shared_ptr<shareddatalayer::SyncStorage> createSyncStorage(std::ostream& out)
20     {
21         try
22         {
23             auto sdl(shareddatalayer::SyncStorage::create());
24             return sdl;
25         }
26         catch (const shareddatalayer::Exception& error)
27         {
28             out << "SyncStorage create failed: " << error.what() << std::endl;
29         }
30
31         out << "Test suspended!" << std::endl;
32         return nullptr;
33     }
34
35     void execRemoveAll(shareddatalayer::SyncStorage& sdl, const std::string& nsStr, std::ostream& out)
36     {
37         try
38         {
39             sdl.removeAll(nsStr);
40         }
41         catch (const shareddatalayer::Exception& error)
42         {
43             out << "removeAll failed: " << error.what() << std::endl;
44         }
45     }
46
47     void execSet(shareddatalayer::SyncStorage& sdl, const std::string& nsStr, const std::string& key, const std::vector<uint8_t>& val, std::ostream& out)
48     {
49         try
50         {
51             sdl.set(nsStr, { { key, val } });
52         }
53         catch (const shareddatalayer::Exception& error)
54         {
55             out << "Set " << key << " failed: " << error.what() << std::endl;
56         }
57     }
58
59     void execGet(shareddatalayer::SyncStorage& sdl, const std::string& nsStr, const std::string& key, const std::vector<uint8_t>& val, std::ostream& out)
60     {
61         try
62         {
63             auto map(sdl.get(nsStr, { key }));
64             auto i(map.find(key));
65             if (i == map.end())
66                 out << "Get " << key << ": Not found!" << std::endl;
67             else if (i->second != val)
68                 out << "Get " << key << ": Wrong value!" << std::endl;
69         }
70         catch (const shareddatalayer::Exception& error)
71         {
72             out << "Get " << key << " failed: " << error.what() << std::endl;
73         }
74     }
75
76     void timeoutThread(const int& timeout)
77     {
78         std::this_thread::sleep_for(std::chrono::seconds(timeout));
79         std::cerr << "SyncStorage create timeout, aborting after " << timeout << " seconds"<< std::endl;
80         std::exit(EXIT_FAILURE);
81     }
82
83     void setTimeout(const int& timeout)
84     {
85         if (timeout)
86         {
87             std::thread t(timeoutThread, timeout);
88             t.detach();
89         }
90     }
91
92     int TestGetSetCommand(std::ostream& out, const boost::program_options::variables_map& map)
93     {
94         auto keyCount(map["key-count"].as<int>());
95         const auto timeout(map["timeout"].as<int>());
96         auto ns(map["ns"].as<std::string>());
97         setTimeout(timeout);
98         auto sdl(createSyncStorage(out));
99         if (sdl == nullptr)
100             return EXIT_FAILURE;
101
102         out << "namespace\t"
103             << "key\t"
104             << "value\t"
105             << "Write\tRead" << std::endl;
106
107         for (uint8_t val(0); 0 < keyCount--; ++val)
108         {
109             auto key("key_" + std::to_string(val));
110
111             auto wStart(std::chrono::high_resolution_clock::now());
112             execSet(std::ref(*sdl), ns, key, {val}, out);
113             auto wEnd(std::chrono::high_resolution_clock::now());
114             auto writeLatency_us = std::chrono::duration_cast<std::chrono::microseconds>(wEnd - wStart);
115
116             auto rStart(std::chrono::high_resolution_clock::now());
117             execGet(std::ref(*sdl), ns, key, {val}, out);
118             auto rEnd(std::chrono::high_resolution_clock::now());
119             auto readLatency_us = std::chrono::duration_cast<std::chrono::microseconds>(rEnd - rStart);
120
121             out << ns << '\t'
122                 << key << '\t'
123                 << std::dec << static_cast<int>(val) << "\t"
124                 << std::dec << writeLatency_us.count() << "\t"
125                 << std::dec << readLatency_us.count() << std::endl;
126         }
127
128         auto start(std::chrono::high_resolution_clock::now());
129         execRemoveAll(std::ref(*sdl), ns, out);
130         auto end(std::chrono::high_resolution_clock::now());
131         auto used_us = std::chrono::duration_cast<std::chrono::microseconds>(end - start);
132         out << "All test keys removed in " << used_us.count() << " microseconds" << std::endl;
133
134         return EXIT_SUCCESS;
135     }
136 }
137
138 AUTO_REGISTER_COMMAND(std::bind(TestGetSetCommand, std::placeholders::_1, std::placeholders::_3),
139                       "test-get-set",
140                       "Write and read to DB and check latency",
141                       "Check that basic SDL api commands (set/get) works normally and measure latency.",
142                       CommandMap::Category::UTIL, 30010,
143                       ("key-count", boost::program_options::value<int>()->default_value(10), "Number of write/read keys")
144                       ("timeout", boost::program_options::value<int>()->default_value(0), "Timeout (in seconds), Default is no timeout")
145                       ("ns", boost::program_options::value<std::string>()->default_value("sdltoolns"), "namespace to use"));