16
16
17
17
#include < array>
18
18
#include < fstream>
19
+ #include < functional>
19
20
#include < iostream>
20
21
#include < memory>
21
22
#include < string>
@@ -40,39 +41,106 @@ using ::firebase::firestore::util::Path;
40
41
// with reason "corruption".
41
42
Path CreateLevelDbDatabaseThatUsesSnappyCompression ();
42
43
43
- // This test ensures that we don't accidentally regress having added in Snappy
44
- // compression support (https://github.com/firebase/firebase-ios-sdk/pull/9596).
45
- TEST (LevelDbSnappy, LevelDbHasSnappySupportCompiledIn) {
46
- // Only run this test in cmake builds, since Snappy support is not included
47
- // when pulling in LevelDb via CocoaPods or Swift Package Manager.
44
+ // Creates and opens a LevelDb database that contains at least one block that
45
+ // is compressed with Snappy compression, then iterates over it, invoking the
46
+ // given callback with the status at each point in the iteration. Once the
47
+ // callback is invoked with a `status` where `status.ok()` is not true, then
48
+ // iteration will stop and the callback will not be invoked again.
49
+ void IterateOverLevelDbDatabaseThatUsesSnappyCompression (
50
+ std::function<void (const leveldb::Status&)>);
51
+
48
52
#if FIRESTORE_TESTS_CMAKE_BUILD
49
- GTEST_SKIP () << " Snappy support is only present in cmake builds" ;
50
- #endif
51
53
52
- Path leveldb_path = CreateLevelDbDatabaseThatUsesSnappyCompression ();
53
- if (HasFatalFailure ()) return ;
54
+ // Ensure that LevelDb is compiled with Snappy compression support.
55
+ // See https://github.com/firebase/firebase-ios-sdk/pull/9596 for details.
56
+ TEST (LevelDbSnappy, LevelDbSupportsSnappy) {
57
+ IterateOverLevelDbDatabaseThatUsesSnappyCompression (
58
+ [](const leveldb::Status& status) {
59
+ ASSERT_TRUE (status.ok ()) << ConvertStatus (status);
60
+ });
61
+ }
62
+
63
+ #else // FIRESTORE_TESTS_CMAKE_BUILD
54
64
55
- leveldb::Options options;
56
- options.create_if_missing = false ;
65
+ // Ensure that LevelDb is NOT compiled with Snappy compression support.
66
+ TEST (LevelDbSnappy, LevelDbDoesNotSupportSnappy) {
67
+ bool got_failed_status = false ;
68
+ IterateOverLevelDbDatabaseThatUsesSnappyCompression (
69
+ [&](const leveldb::Status& status) {
70
+ if (!status.ok ()) {
71
+ got_failed_status = true ;
72
+ ASSERT_TRUE (status.IsCorruption ()) << ConvertStatus (status);
73
+ }
74
+ });
57
75
76
+ if (!HasFailure ()) {
77
+ ASSERT_TRUE (got_failed_status)
78
+ << " Reading a Snappy-compressed LevelDb database was successful; "
79
+ " however, it should NOT have been successful "
80
+ " since Snappy support is expected to NOT be available." ;
81
+ }
82
+ }
83
+
84
+ #endif // FIRESTORE_TESTS_CMAKE_BUILD
85
+
86
+ void IterateOverLevelDbDatabaseThatUsesSnappyCompression (
87
+ std::function<void (const leveldb::Status&)> callback) {
58
88
std::unique_ptr<leveldb::DB> db;
59
89
{
90
+ Path leveldb_path = CreateLevelDbDatabaseThatUsesSnappyCompression ();
91
+
92
+ leveldb::Options options;
93
+ options.create_if_missing = false ;
94
+
60
95
leveldb::DB* db_ptr;
61
96
leveldb::Status status =
62
97
leveldb::DB::Open (options, leveldb_path.ToUtf8String (), &db_ptr);
63
- ASSERT_TRUE (status.ok ());
98
+
99
+ ASSERT_TRUE (status.ok ())
100
+ << " Opening LevelDb database " << leveldb_path.ToUtf8String ()
101
+ << " failed: " << ConvertStatus (status);
102
+
64
103
db.reset (db_ptr);
65
104
}
66
105
67
- // One of the assertions below will fail when LevelDb attempts to read a block
68
- // that is compressed with Snappy and Snappy compression support is not
69
- // compiled in.
70
106
std::unique_ptr<leveldb::Iterator> it (
71
107
db->NewIterator (leveldb::ReadOptions ()));
72
108
for (it->SeekToFirst (); it->Valid (); it->Next ()) {
73
- ASSERT_TRUE (it->status ().ok ()) << ConvertStatus (it->status ());
109
+ callback (it->status ());
110
+ if (!it->status ().ok ()) {
111
+ return ;
112
+ }
113
+ }
114
+
115
+ // Invoke the callback on the final status.
116
+ callback (it->status ());
117
+ }
118
+
119
+ template <typename T>
120
+ void WriteFile (const Path& dir,
121
+ const std::string& file_name,
122
+ const T& data_array) {
123
+ Filesystem* fs = Filesystem::Default ();
124
+ {
125
+ auto status = fs->RecursivelyCreateDir (dir);
126
+ if (!status.ok ()) {
127
+ FAIL () << " Creating directory failed: " << dir.ToUtf8String () << " ("
128
+ << status.error_message () << " )" ;
129
+ }
130
+ }
131
+
132
+ Path file = dir.AppendUtf8 (file_name);
133
+ std::ofstream out_file (file.native_value (), std::ios::binary);
134
+ if (!out_file) {
135
+ FAIL () << " Unable to open file for writing: " << file.ToUtf8String ();
136
+ }
137
+
138
+ out_file.write (reinterpret_cast <const char *>(data_array.data ()),
139
+ data_array.size ());
140
+ out_file.close ();
141
+ if (!out_file) {
142
+ FAIL () << " Writing to file failed: " << file.ToUtf8String ();
74
143
}
75
- ASSERT_TRUE (it->status ().ok ()) << ConvertStatus (it->status ());
76
144
}
77
145
78
146
const std::array<unsigned char , 0x00000165 > LevelDbSnappyFile_000005_ldb{
@@ -190,33 +258,6 @@ const std::array<unsigned char, 0x000000C2> LevelDbSnappyFile_MANIFEST_000084{
190
258
0x04 , 0x0D ,
191
259
};
192
260
193
- template <typename T>
194
- void WriteFile (const Path& dir,
195
- const std::string& file_name,
196
- const T& data_array) {
197
- Filesystem* fs = Filesystem::Default ();
198
- {
199
- auto status = fs->RecursivelyCreateDir (dir);
200
- if (!status.ok ()) {
201
- FAIL () << " Creating directory failed: " << dir.ToUtf8String () << " ("
202
- << status.error_message () << " )" ;
203
- }
204
- }
205
-
206
- Path file = dir.AppendUtf8 (file_name);
207
- std::ofstream out_file (file.native_value (), std::ios::binary);
208
- if (!out_file) {
209
- FAIL () << " Unable to open file for writing: " << file.ToUtf8String ();
210
- }
211
-
212
- out_file.write (reinterpret_cast <const char *>(data_array.data ()),
213
- data_array.size ());
214
- out_file.close ();
215
- if (!out_file) {
216
- FAIL () << " Writing to file failed: " << file.ToUtf8String ();
217
- }
218
- }
219
-
220
261
Path CreateLevelDbDatabaseThatUsesSnappyCompression () {
221
262
Path leveldb_dir = ::firebase::firestore::local::LevelDbDir ();
222
263
WriteFile (leveldb_dir, " 000005.ldb" , LevelDbSnappyFile_000005_ldb);
0 commit comments