Add backend id to database scheme
[platform/core/security/key-manager.git] / tests / DBFixture.cpp
1 #include <boost/test/unit_test.hpp>
2 #include <db-crypto.h>
3 #include <ckm/ckm-error.h>
4 #include <DBFixture.h>
5 #include <fstream>
6
7 using namespace CKM;
8 using namespace std::chrono;
9
10
11 DBFixture::DBFixture()
12 {
13     BOOST_CHECK(unlink(m_crypto_db_fname) == 0 || errno == ENOENT);
14     init();
15 }
16 DBFixture::DBFixture(const char *db_fname)
17 {
18     BOOST_CHECK(unlink(m_crypto_db_fname) == 0 || errno == ENOENT);
19
20     // copy file
21     std::ifstream f1(db_fname, std::fstream::binary);
22     std::ofstream f2(m_crypto_db_fname, std::fstream::trunc|std::fstream::binary);
23     f2 << f1.rdbuf();
24     f2.close();
25     f1.close();
26
27     init();
28 }
29
30 void DBFixture::init()
31 {
32     high_resolution_clock::time_point srand_feed = high_resolution_clock::now();
33     srand(srand_feed.time_since_epoch().count());
34
35     BOOST_REQUIRE_NO_THROW(m_db = DB::Crypto(m_crypto_db_fname, defaultPass));
36 }
37
38 double DBFixture::performance_get_time_elapsed_ms()
39 {
40     return duration_cast<milliseconds>(m_end_time - m_start_time).count();
41 }
42
43 void DBFixture::performance_start(const char *operation_name)
44 {
45     m_operation = std::string(operation_name?operation_name:"unknown");
46     BOOST_TEST_MESSAGE("\t<performance> running " << m_operation << " performance test...");
47     m_start_time = high_resolution_clock::now();
48 }
49
50 void DBFixture::performance_stop(long num_operations_performed)
51 {
52     m_end_time = high_resolution_clock::now();
53     double time_elapsed_ms = performance_get_time_elapsed_ms();
54     BOOST_TEST_MESSAGE("\t<performance> time elapsed: " << time_elapsed_ms << "[ms], number of " << m_operation << ": " << num_operations_performed);
55     if(num_operations_performed>0)
56         BOOST_TEST_MESSAGE("\t<performance> average time per " << m_operation << ": " << time_elapsed_ms/num_operations_performed << "[ms]");
57 }
58
59 void DBFixture::generate_name(unsigned int id, Name & output)
60 {
61     std::stringstream ss;
62     ss << "name_no_" << id;
63     output = ss.str();
64 }
65
66 void DBFixture::generate_label(unsigned int id, Label & output)
67 {
68     std::stringstream ss;
69     ss << "label_no_" << id;
70     output = ss.str();
71 }
72
73 void DBFixture::generate_perf_DB(unsigned int num_name, unsigned int num_elements)
74 {
75     // to speed up data creation - cache the row
76     DB::Row rowPattern = create_default_row(DataType::BINARY_DATA);
77     rowPattern.data = RawBuffer(100, 20);
78     rowPattern.dataSize = rowPattern.data.size();
79     rowPattern.tag = RawBuffer(AES_GCM_TAG_SIZE, 1);
80
81     for(unsigned int i=0; i<num_name; i++)
82     {
83         generate_name(i, rowPattern.name);
84         generate_label(i/num_elements, rowPattern.ownerLabel);
85
86         BOOST_REQUIRE_NO_THROW(m_db.saveRow(rowPattern));
87     }
88 }
89
90 long DBFixture::add_full_access_rights(unsigned int num_name, unsigned int num_name_per_label)
91 {
92     long iterations = 0;
93     unsigned int num_labels = num_name / num_name_per_label;
94     Name name;
95     Label owner_label, accessor_label;
96     for(unsigned int a=0; a<num_name; a++)
97     {
98         generate_name(a, name);
99         generate_label(a/num_name_per_label, owner_label);
100         for(unsigned int l=0; l<num_labels; l++)
101         {
102             // bypass the owner label
103             if(l == (a/num_name_per_label))
104                 continue;
105
106             // add permission
107             generate_label(l, accessor_label);
108             add_permission(name, owner_label, accessor_label);
109             iterations ++;
110         }
111     }
112
113     return iterations;
114 }
115
116 DB::Row DBFixture::create_default_row(DataType type)
117 {
118     return create_default_row(m_default_name, m_default_label, type);
119 }
120
121 DB::Row DBFixture::create_default_row(const Name &name,
122                                     const Label &label,
123                                     DataType type)
124 {
125     DB::Row row;
126     row.name = name;
127     row.ownerLabel = label;
128     row.exportable = 1;
129     row.algorithmType = DBCMAlgType::AES_GCM_256;
130     row.dataType = type;
131     row.iv = createDefaultPass();
132     row.encryptionScheme = 0;
133     row.dataSize = 0;
134     row.backendId = CryptoBackend::OpenSSL;
135
136     return row;
137 }
138
139 void DBFixture::compare_row(const DB::Row &lhs, const DB::Row &rhs)
140 {
141     BOOST_CHECK_MESSAGE(lhs.name == rhs.name,
142             "namees didn't match! Got: " << rhs.name
143                 << " , expected : " << lhs.name);
144
145     BOOST_CHECK_MESSAGE(lhs.ownerLabel == rhs.ownerLabel,
146             "smackLabel didn't match! Got: " << rhs.ownerLabel
147                 << " , expected : " << lhs.ownerLabel);
148
149     BOOST_CHECK_MESSAGE(lhs.exportable == rhs.exportable,
150             "exportable didn't match! Got: " << rhs.exportable
151                 << " , expected : " << lhs.exportable);
152
153     BOOST_CHECK_MESSAGE(lhs.iv == rhs.iv,
154             "iv didn't match! Got: " << rhs.iv.size()
155                 << " , expected : " << lhs.iv.size());
156
157     BOOST_CHECK_MESSAGE(lhs.data == rhs.data,
158             "data didn't match! Got: " << rhs.data.size()
159                 << " , expected : " << lhs.data.size());
160
161     BOOST_CHECK_MESSAGE(lhs.backendId == rhs.backendId,
162             "backendId didn't match! Got: " << static_cast<int>(rhs.backendId)
163                 << " , expected : " << static_cast<int>(lhs.backendId));
164 }
165
166 void DBFixture::check_DB_integrity(const DB::Row &rowPattern)
167 {
168     BOOST_REQUIRE_NO_THROW(m_db.saveRow(rowPattern));
169
170     DB::Crypto::RowOptional optional_row;
171     BOOST_REQUIRE_NO_THROW(optional_row = m_db.getRow("name", "label", DataType::BINARY_DATA));
172     BOOST_REQUIRE_MESSAGE(optional_row, "Select didn't return any row");
173
174     compare_row(*optional_row, rowPattern);
175     DB::Row name_duplicate = rowPattern;
176     name_duplicate.data = createDefaultPass();
177     name_duplicate.dataSize = name_duplicate.data.size();
178
179     unsigned int erased;
180     BOOST_REQUIRE_NO_THROW(erased = m_db.deleteRow("name", "label"));
181     BOOST_REQUIRE_MESSAGE(erased > 0, "Inserted row didn't exist in db");
182
183     DB::Crypto::RowOptional row_optional;
184     BOOST_REQUIRE_NO_THROW(row_optional = m_db.getRow("name", "label", DataType::BINARY_DATA));
185     BOOST_REQUIRE_MESSAGE(!row_optional, "Select should not return row after deletion");
186 }
187
188 void DBFixture::insert_row()
189 {
190     insert_row(m_default_name, m_default_label);
191 }
192
193 void DBFixture::insert_row(const Name &name, const Label &owner_label)
194 {
195     DB::Row rowPattern = create_default_row(name, owner_label, DataType::BINARY_DATA);
196     rowPattern.data = RawBuffer(100, 20);
197     rowPattern.dataSize = rowPattern.data.size();
198     rowPattern.tag = RawBuffer(AES_GCM_TAG_SIZE, 1);
199     BOOST_REQUIRE_NO_THROW(m_db.saveRow(rowPattern));
200 }
201
202 void DBFixture::delete_row(const Name &name, const Label &owner_label)
203 {
204     bool exit_flag;
205     BOOST_REQUIRE_NO_THROW(exit_flag = m_db.deleteRow(name, owner_label));
206     BOOST_REQUIRE_MESSAGE(true == exit_flag, "remove name failed: no rows removed");
207 }
208
209 void DBFixture::add_permission(const Name &name, const Label &owner_label, const Label &accessor_label)
210 {
211     BOOST_REQUIRE_NO_THROW(m_db.setPermission(name,
212                                               owner_label,
213                                               accessor_label,
214                                               CKM::Permission::READ | CKM::Permission::REMOVE));
215 }
216
217 void DBFixture::read_row_expect_success(const Name &name, const Label &owner_label)
218 {
219     DB::Crypto::RowOptional row;
220     BOOST_REQUIRE_NO_THROW(row = m_db.getRow(name, owner_label, DataType::BINARY_DATA));
221     BOOST_REQUIRE_MESSAGE(row, "row is empty");
222     BOOST_REQUIRE_MESSAGE(row->name == name, "name is not valid");
223 }