Fix SVACE and C++ issues
[platform/core/security/key-manager.git] / tests / DBFixture.cpp
1 /*
2  *  Copyright (c) 2016 Samsung Electronics Co., Ltd All Rights Reserved
3  *
4  *  Contact: Kyungwook Tak <k.tak@samsung.com>
5  *
6  *  Licensed under the Apache License, Version 2.0 (the "License");
7  *  you may not use this file except in compliance with the License.
8  *  You may obtain a copy of the License at
9  *
10  *      http://www.apache.org/licenses/LICENSE-2.0
11  *
12  *  Unless required by applicable law or agreed to in writing, software
13  *  distributed under the License is distributed on an "AS IS" BASIS,
14  *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15  *  See the License for the specific language governing permissions and
16  *  limitations under the License
17  *
18  * @file        DBFixture.cpp
19  * @author      Maciej Karpiuk (m.karpiuk2@samsung.com)
20  * @version
21  * @brief
22  */
23 #include <boost/test/unit_test.hpp>
24 #include <db-crypto.h>
25 #include <ckm/ckm-error.h>
26 #include <DBFixture.h>
27 #include <fstream>
28
29 using namespace CKM;
30 using namespace std::chrono;
31
32
33 DBFixture::DBFixture()
34 {
35         BOOST_CHECK(unlink(m_crypto_db_fname) == 0 || errno == ENOENT);
36         init();
37 }
38 DBFixture::DBFixture(const char *db_fname)
39 {
40         BOOST_CHECK(unlink(m_crypto_db_fname) == 0 || errno == ENOENT);
41
42         // copy file
43         std::ifstream f1(db_fname, std::fstream::binary);
44         std::ofstream f2(m_crypto_db_fname, std::fstream::trunc | std::fstream::binary);
45         f2 << f1.rdbuf();
46         f2.close();
47         f1.close();
48
49         init();
50 }
51
52 void DBFixture::init()
53 {
54         high_resolution_clock::time_point srand_feed = high_resolution_clock::now();
55         srand(srand_feed.time_since_epoch().count());
56
57         BOOST_REQUIRE_NO_THROW(m_db = DB::Crypto(m_crypto_db_fname, defaultPass));
58 }
59
60 double DBFixture::performance_get_time_elapsed_ms()
61 {
62         return duration_cast<milliseconds>(m_end_time - m_start_time).count();
63 }
64
65 void DBFixture::performance_start(const char *operation_name)
66 {
67         m_operation = std::string(operation_name ? operation_name : "unknown");
68         BOOST_TEST_MESSAGE("\t<performance> running " << m_operation <<
69                                            " performance test...");
70         m_start_time = high_resolution_clock::now();
71 }
72
73 void DBFixture::performance_stop(long num_operations_performed)
74 {
75         m_end_time = high_resolution_clock::now();
76         double time_elapsed_ms = performance_get_time_elapsed_ms();
77         BOOST_TEST_MESSAGE("\t<performance> time elapsed: " << time_elapsed_ms <<
78                                            "[ms], number of " << m_operation << ": " << num_operations_performed);
79
80         if (num_operations_performed > 0)
81                 BOOST_TEST_MESSAGE("\t<performance> average time per " << m_operation << ": " <<
82                                                    time_elapsed_ms / num_operations_performed << "[ms]");
83 }
84
85 void DBFixture::generate_name(unsigned int id, Name &output)
86 {
87         std::stringstream ss;
88         ss << "name_no_" << id;
89         output = ss.str();
90 }
91
92 void DBFixture::generate_owner(unsigned int id, ClientId &output)
93 {
94         std::stringstream ss;
95         ss << "label_no_" << id;
96         output = ss.str();
97 }
98
99 void DBFixture::generate_perf_DB(unsigned int num_name,
100                                                                  unsigned int names_per_owner)
101 {
102         // to speed up data creation - cache the row
103         DB::Row rowPattern = create_default_row(DataType::BINARY_DATA);
104         rowPattern.data = RawBuffer(100, 20);
105         rowPattern.dataSize = rowPattern.data.size();
106         rowPattern.tag = RawBuffer(AES_GCM_TAG_SIZE, 1);
107
108         for (unsigned int i = 0; i < num_name; i++) {
109                 generate_name(i, rowPattern.name);
110                 generate_owner(i / names_per_owner, rowPattern.owner);
111
112                 BOOST_REQUIRE_NO_THROW(m_db.saveRow(rowPattern));
113         }
114 }
115
116 long DBFixture::add_full_access_rights(unsigned int num_name,
117                                                                            unsigned int num_name_per_owner)
118 {
119         long iterations = 0;
120         unsigned int num_owners = num_name / num_name_per_owner;
121         Name name;
122         ClientId owner, accessor;
123
124         for (unsigned int a = 0; a < num_name; a++) {
125                 generate_name(a, name);
126                 generate_owner(a / num_name_per_owner, owner);
127
128                 for (unsigned int l = 0; l < num_owners; l++) {
129                         // bypass the owner
130                         if (l == (a / num_name_per_owner))
131                                 continue;
132
133                         // add permission
134                         generate_owner(l, accessor);
135                         add_permission(name, owner, accessor);
136                         iterations++;
137                 }
138         }
139
140         return iterations;
141 }
142
143 DB::Row DBFixture::create_default_row(DataType type)
144 {
145         return create_default_row(m_default_name, m_default_owner, type);
146 }
147
148 DB::Row DBFixture::create_default_row(const Name &name,
149                                                                           const ClientId &owner,
150                                                                           DataType type)
151 {
152         DB::Row row;
153         row.name = name;
154         row.owner = owner;
155         row.exportable = 1;
156         row.algorithmType = DBCMAlgType::AES_GCM_256;
157         row.dataType = type;
158         row.iv = createDefaultPass();
159         row.encryptionScheme = 0;
160         row.dataSize = 0;
161         row.backendId = CryptoBackend::OpenSSL;
162
163         return row;
164 }
165
166 void DBFixture::compare_row(const DB::Row &lhs, const DB::Row &rhs)
167 {
168         BOOST_CHECK_MESSAGE(lhs.name == rhs.name,
169                                                 "namees didn't match! Got: " << rhs.name
170                                                 << " , expected : " << lhs.name);
171
172         BOOST_CHECK_MESSAGE(lhs.owner == rhs.owner,
173                                                 "owner didn't match! Got: " << rhs.owner
174                                                 << " , expected : " << lhs.owner);
175
176         BOOST_CHECK_MESSAGE(lhs.exportable == rhs.exportable,
177                                                 "exportable didn't match! Got: " << rhs.exportable
178                                                 << " , expected : " << lhs.exportable);
179
180         BOOST_CHECK_MESSAGE(lhs.iv == rhs.iv,
181                                                 "iv didn't match! Got: " << rhs.iv.size()
182                                                 << " , expected : " << lhs.iv.size());
183
184         BOOST_CHECK_MESSAGE(lhs.data == rhs.data,
185                                                 "data didn't match! Got: " << rhs.data.size()
186                                                 << " , expected : " << lhs.data.size());
187
188         BOOST_CHECK_MESSAGE(lhs.backendId == rhs.backendId,
189                                                 "backendId didn't match! Got: " << static_cast<int>(rhs.backendId)
190                                                 << " , expected : " << static_cast<int>(lhs.backendId));
191 }
192
193 void DBFixture::check_DB_integrity(const DB::Row &rowPattern)
194 {
195         BOOST_REQUIRE_NO_THROW(m_db.saveRow(rowPattern));
196
197         DB::Crypto::RowOptional optional_row;
198         BOOST_REQUIRE_NO_THROW(optional_row = m_db.getRow(m_default_name, m_default_owner,
199                                                                                   DataType::BINARY_DATA));
200         BOOST_REQUIRE_MESSAGE(optional_row, "Select didn't return any row");
201
202         compare_row(*optional_row, rowPattern);
203         DB::Row name_duplicate = rowPattern;
204         name_duplicate.data = createDefaultPass();
205         name_duplicate.dataSize = name_duplicate.data.size();
206
207         unsigned int erased;
208         BOOST_REQUIRE_NO_THROW(erased = m_db.deleteRow(m_default_name, m_default_owner));
209         BOOST_REQUIRE_MESSAGE(erased > 0, "Inserted row didn't exist in db");
210
211         DB::Crypto::RowOptional row_optional;
212         BOOST_REQUIRE_NO_THROW(row_optional = m_db.getRow(m_default_name, m_default_owner,
213                                                                                   DataType::BINARY_DATA));
214         BOOST_REQUIRE_MESSAGE(!row_optional,
215                                                   "Select should not return row after deletion");
216 }
217
218 void DBFixture::insert_row()
219 {
220         insert_row(m_default_name, m_default_owner);
221 }
222
223 void DBFixture::insert_row(const Name &name, const ClientId &owner)
224 {
225         DB::Row rowPattern = create_default_row(name, owner,
226                                                                                         DataType::BINARY_DATA);
227         rowPattern.data = RawBuffer(100, 20);
228         rowPattern.dataSize = rowPattern.data.size();
229         rowPattern.tag = RawBuffer(AES_GCM_TAG_SIZE, 1);
230         BOOST_REQUIRE_NO_THROW(m_db.saveRow(rowPattern));
231 }
232
233 void DBFixture::delete_row(const Name &name, const ClientId &owner)
234 {
235         bool exit_flag;
236         BOOST_REQUIRE_NO_THROW(exit_flag = m_db.deleteRow(name, owner));
237         BOOST_REQUIRE_MESSAGE(true == exit_flag, "remove name failed: no rows removed");
238 }
239
240 void DBFixture::add_permission(const Name &name, const ClientId &owner,
241                                                            const ClientId &accessor)
242 {
243         BOOST_REQUIRE_NO_THROW(m_db.setPermission(name,
244                                                    owner,
245                                                    accessor,
246                                                    CKM::Permission::READ | CKM::Permission::REMOVE));
247 }
248
249 void DBFixture::read_row_expect_success(const Name &name,
250                                                                                 const ClientId &owner)
251 {
252         DB::Crypto::RowOptional row;
253         BOOST_REQUIRE_NO_THROW(row = m_db.getRow(name, owner,
254                                                                  DataType::BINARY_DATA));
255         BOOST_REQUIRE_MESSAGE(row, "row is empty");
256         BOOST_REQUIRE_MESSAGE(row->name == name, "name is not valid");
257 }