diff options
19 files changed, 462 insertions, 363 deletions
diff --git a/Firestore/Example/Firestore.xcodeproj/project.pbxproj b/Firestore/Example/Firestore.xcodeproj/project.pbxproj index 7c6508a..6a5b795 100644 --- a/Firestore/Example/Firestore.xcodeproj/project.pbxproj +++ b/Firestore/Example/Firestore.xcodeproj/project.pbxproj @@ -67,6 +67,8 @@ AB356EF7200EA5EB0089B766 /* field_value_test.cc in Sources */ = {isa = PBXBuildFile; fileRef = AB356EF6200EA5EB0089B766 /* field_value_test.cc */; }; AB380CFB2019388600D97691 /* target_id_generator_test.cc in Sources */ = {isa = PBXBuildFile; fileRef = AB380CF82019382300D97691 /* target_id_generator_test.cc */; }; AB380CFE201A2F4500D97691 /* string_util_test.cc in Sources */ = {isa = PBXBuildFile; fileRef = AB380CFC201A2EE200D97691 /* string_util_test.cc */; }; + AB380D02201BC69F00D97691 /* bits_test.cc in Sources */ = {isa = PBXBuildFile; fileRef = AB380D01201BC69F00D97691 /* bits_test.cc */; }; + AB380D04201BC6E400D97691 /* ordered_code_test.cc in Sources */ = {isa = PBXBuildFile; fileRef = AB380D03201BC6E400D97691 /* ordered_code_test.cc */; }; AB382F7C1FE02A1F007CA955 /* FIRDocumentReferenceTests.m in Sources */ = {isa = PBXBuildFile; fileRef = AB382F7B1FE02A1F007CA955 /* FIRDocumentReferenceTests.m */; }; AB382F7E1FE03059007CA955 /* FIRFieldPathTests.m in Sources */ = {isa = PBXBuildFile; fileRef = AB382F7D1FE03059007CA955 /* FIRFieldPathTests.m */; }; AB7BAB342012B519001E0872 /* geo_point_test.cc in Sources */ = {isa = PBXBuildFile; fileRef = AB7BAB332012B519001E0872 /* geo_point_test.cc */; }; @@ -251,6 +253,8 @@ AB356EF6200EA5EB0089B766 /* field_value_test.cc */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = field_value_test.cc; sourceTree = "<group>"; }; AB380CF82019382300D97691 /* target_id_generator_test.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = target_id_generator_test.cc; sourceTree = "<group>"; }; AB380CFC201A2EE200D97691 /* string_util_test.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = string_util_test.cc; path = ../../core/test/firebase/firestore/util/string_util_test.cc; sourceTree = "<group>"; }; + AB380D01201BC69F00D97691 /* bits_test.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = bits_test.cc; path = ../../core/test/firebase/firestore/util/bits_test.cc; sourceTree = "<group>"; }; + AB380D03201BC6E400D97691 /* ordered_code_test.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = ordered_code_test.cc; path = ../../core/test/firebase/firestore/util/ordered_code_test.cc; sourceTree = "<group>"; }; AB382F7B1FE02A1F007CA955 /* FIRDocumentReferenceTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FIRDocumentReferenceTests.m; sourceTree = "<group>"; }; AB382F7D1FE03059007CA955 /* FIRFieldPathTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FIRFieldPathTests.m; sourceTree = "<group>"; }; AB7BAB332012B519001E0872 /* geo_point_test.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = geo_point_test.cc; path = ../../core/test/firebase/firestore/geo_point_test.cc; sourceTree = "<group>"; }; @@ -404,8 +408,10 @@ children = ( 548DB926200D590300E00ABC /* assert_test.cc */, 54740A521FC913E500713A1A /* autoid_test.cc */, + AB380D01201BC69F00D97691 /* bits_test.cc */, 548DB928200D59F600E00ABC /* comparison_test.cc */, 54C2294E1FECABAE007D065B /* log_test.cc */, + AB380D03201BC6E400D97691 /* ordered_code_test.cc */, 54740A531FC913E500713A1A /* secure_random_test.cc */, 5436F32320008FAD006E51E3 /* string_printf_test.cc */, AB380CFC201A2EE200D97691 /* string_util_test.cc */, @@ -418,7 +424,6 @@ children = ( AB380CF7201937B800D97691 /* core */, AB356EF5200E9D1A0089B766 /* model */, - 54764FAD1FAA0C650085E60A /* Port */, 54740A561FC913EB00713A1A /* util */, 54764FAE1FAA21B90085E60A /* FSTGoogleTestTests.mm */, AB7BAB332012B519001E0872 /* geo_point_test.cc */, @@ -426,13 +431,6 @@ name = GoogleTests; sourceTree = "<group>"; }; - 54764FAD1FAA0C650085E60A /* Port */ = { - isa = PBXGroup; - children = ( - ); - name = Port; - sourceTree = "<group>"; - }; 6003F581195388D10070C39A = { isa = PBXGroup; children = ( @@ -594,31 +592,31 @@ DE51B1621F0D48AC0013853F /* Local */ = { isa = PBXGroup; children = ( - 61E1D8AF1FCF6AF500753285 /* StringViewTests.mm */, - DE51B16A1F0D48AC0013853F /* FSTLocalStoreTests.h */, - DE51B1701F0D48AC0013853F /* FSTMutationQueueTests.h */, - DE51B1721F0D48AC0013853F /* FSTPersistenceTestHelpers.h */, - DE51B1741F0D48AC0013853F /* FSTQueryCacheTests.h */, - DE51B1771F0D48AC0013853F /* FSTRemoteDocumentCacheTests.h */, DE51B1631F0D48AC0013853F /* FSTEagerGarbageCollectorTests.m */, + DE51B1641F0D48AC0013853F /* FSTLevelDBKeyTests.mm */, DE51B1651F0D48AC0013853F /* FSTLevelDBLocalStoreTests.m */, + DE51B1661F0D48AC0013853F /* FSTLevelDBMutationQueueTests.mm */, DE51B1671F0D48AC0013853F /* FSTLevelDBQueryCacheTests.m */, + DE51B1681F0D48AC0013853F /* FSTLevelDBRemoteDocumentCacheTests.mm */, DE51B1691F0D48AC0013853F /* FSTLocalSerializerTests.m */, + DE51B16A1F0D48AC0013853F /* FSTLocalStoreTests.h */, DE51B16B1F0D48AC0013853F /* FSTLocalStoreTests.m */, DE51B16C1F0D48AC0013853F /* FSTMemoryLocalStoreTests.m */, DE51B16D1F0D48AC0013853F /* FSTMemoryMutationQueueTests.m */, DE51B16E1F0D48AC0013853F /* FSTMemoryQueryCacheTests.m */, DE51B16F1F0D48AC0013853F /* FSTMemoryRemoteDocumentCacheTests.m */, + DE51B1701F0D48AC0013853F /* FSTMutationQueueTests.h */, DE51B1711F0D48AC0013853F /* FSTMutationQueueTests.m */, + DE51B1721F0D48AC0013853F /* FSTPersistenceTestHelpers.h */, DE51B1731F0D48AC0013853F /* FSTPersistenceTestHelpers.m */, + DE51B1741F0D48AC0013853F /* FSTQueryCacheTests.h */, DE51B1751F0D48AC0013853F /* FSTQueryCacheTests.m */, DE51B1761F0D48AC0013853F /* FSTReferenceSetTests.m */, + DE51B1771F0D48AC0013853F /* FSTRemoteDocumentCacheTests.h */, DE51B1781F0D48AC0013853F /* FSTRemoteDocumentCacheTests.m */, DE51B1791F0D48AC0013853F /* FSTRemoteDocumentChangeBufferTests.m */, - DE51B1641F0D48AC0013853F /* FSTLevelDBKeyTests.mm */, - DE51B1661F0D48AC0013853F /* FSTLevelDBMutationQueueTests.mm */, - DE51B1681F0D48AC0013853F /* FSTLevelDBRemoteDocumentCacheTests.mm */, DE51B17A1F0D48AC0013853F /* FSTWriteGroupTests.mm */, + 61E1D8AF1FCF6AF500753285 /* StringViewTests.mm */, ); path = Local; sourceTree = "<group>"; @@ -1274,6 +1272,7 @@ DE51B1E01F0D490D0013853F /* FSTMemoryQueryCacheTests.m in Sources */, DE51B1E91F0D490D0013853F /* FSTLevelDBMutationQueueTests.mm in Sources */, 54764FAF1FAA21B90085E60A /* FSTGoogleTestTests.mm in Sources */, + AB380D04201BC6E400D97691 /* ordered_code_test.cc in Sources */, DE51B1E61F0D490D0013853F /* FSTRemoteDocumentCacheTests.m in Sources */, 61E1D8B11FCF6C5700753285 /* StringViewTests.mm in Sources */, DE51B1D91F0D490D0013853F /* FSTEagerGarbageCollectorTests.m in Sources */, @@ -1290,6 +1289,7 @@ DE51B1FC1F0D492C0013853F /* FSTMockDatastore.m in Sources */, DE51B1CE1F0D48CD0013853F /* FSTEventManagerTests.m in Sources */, DE51B1E41F0D490D0013853F /* FSTQueryCacheTests.m in Sources */, + AB380D02201BC69F00D97691 /* bits_test.cc in Sources */, DE51B1CD1F0D48CD0013853F /* FSTDatabaseInfoTests.m in Sources */, AB382F7E1FE03059007CA955 /* FIRFieldPathTests.m in Sources */, 548DB929200D59F600E00ABC /* comparison_test.cc in Sources */, diff --git a/Firestore/Example/Tests/Local/FSTLevelDBMutationQueueTests.mm b/Firestore/Example/Tests/Local/FSTLevelDBMutationQueueTests.mm index 6c26fd9..fe79598 100644 --- a/Firestore/Example/Tests/Local/FSTLevelDBMutationQueueTests.mm +++ b/Firestore/Example/Tests/Local/FSTLevelDBMutationQueueTests.mm @@ -19,7 +19,6 @@ #import <XCTest/XCTest.h> #include <leveldb/db.h> -#include "Firestore/Port/ordered_code.h" #import "Firestore/Protos/objc/firestore/local/Mutation.pbobjc.h" #import "Firestore/Source/Auth/FSTUser.h" #import "Firestore/Source/Local/FSTLevelDB.h" @@ -29,6 +28,8 @@ #import "Firestore/Example/Tests/Local/FSTMutationQueueTests.h" #import "Firestore/Example/Tests/Local/FSTPersistenceTestHelpers.h" +#include "Firestore/core/src/firebase/firestore/util/ordered_code.h" + NS_ASSUME_NONNULL_BEGIN using leveldb::DB; @@ -36,7 +37,7 @@ using leveldb::Slice; using leveldb::Status; using leveldb::WriteOptions; using Firestore::StringView; -using Firestore::OrderedCode; +using firebase::firestore::util::OrderedCode; // A dummy mutation value, useful for testing code that's known to examine only mutation keys. static const char *kDummy = "1"; diff --git a/Firestore/Example/Tests/Local/FSTLevelDBRemoteDocumentCacheTests.mm b/Firestore/Example/Tests/Local/FSTLevelDBRemoteDocumentCacheTests.mm index 1f84aa6..638ab2f 100644 --- a/Firestore/Example/Tests/Local/FSTLevelDBRemoteDocumentCacheTests.mm +++ b/Firestore/Example/Tests/Local/FSTLevelDBRemoteDocumentCacheTests.mm @@ -18,16 +18,17 @@ #include <leveldb/db.h> -#include "Firestore/Port/ordered_code.h" #import "Firestore/Source/Local/FSTLevelDB.h" #import "Firestore/Source/Local/FSTLevelDBKey.h" #import "Firestore/Example/Tests/Local/FSTPersistenceTestHelpers.h" +#include "Firestore/core/src/firebase/firestore/util/ordered_code.h" + NS_ASSUME_NONNULL_BEGIN using leveldb::WriteOptions; -using Firestore::OrderedCode; +using firebase::firestore::util::OrderedCode; // A dummy document value, useful for testing code that's known to examine only document keys. static const char *kDummy = "1"; diff --git a/Firestore/Source/Local/FSTLevelDBKey.mm b/Firestore/Source/Local/FSTLevelDBKey.mm index 074d5c5..9850fff 100644 --- a/Firestore/Source/Local/FSTLevelDBKey.mm +++ b/Firestore/Source/Local/FSTLevelDBKey.mm @@ -18,13 +18,14 @@ #include <string> -#include "Firestore/Port/ordered_code.h" #import "Firestore/Source/Model/FSTDocumentKey.h" #import "Firestore/Source/Model/FSTPath.h" +#include "Firestore/core/src/firebase/firestore/util/ordered_code.h" + NS_ASSUME_NONNULL_BEGIN -using Firestore::OrderedCode; +using firebase::firestore::util::OrderedCode; using Firestore::StringView; using leveldb::Slice; @@ -109,11 +110,11 @@ void WriteComponentLabel(std::string *dest, FSTComponentLabel label) { */ BOOL ReadComponentLabel(leveldb::Slice *contents, FSTComponentLabel *label) { int64_t rawResult = 0; - Slice tmp = *contents; + absl::string_view tmp(contents->data(), contents->size()); if (OrderedCode::ReadSignedNumIncreasing(&tmp, &rawResult)) { if (rawResult >= FSTComponentLabelTerminator && rawResult <= FSTComponentLabelUnknown) { *label = static_cast<FSTComponentLabel>(rawResult); - *contents = tmp; + *contents = leveldb::Slice(tmp.data(), tmp.size()); return YES; } } @@ -128,9 +129,9 @@ BOOL ReadComponentLabel(leveldb::Slice *contents, FSTComponentLabel *label) { * * If the read is successful, returns YES and contents will be updated to the next unread byte. */ -BOOL ReadComponentLabelMatching(Slice *contents, FSTComponentLabel expectedLabel) { +BOOL ReadComponentLabelMatching(absl::string_view *contents, FSTComponentLabel expectedLabel) { int64_t rawResult = 0; - Slice tmp = *contents; + absl::string_view tmp = *contents; if (OrderedCode::ReadSignedNumIncreasing(&tmp, &rawResult)) { if (rawResult == expectedLabel) { *contents = tmp; @@ -152,10 +153,10 @@ BOOL ReadComponentLabelMatching(Slice *contents, FSTComponentLabel expectedLabel */ BOOL ReadInt32(Slice *contents, int32_t *result) { int64_t rawResult = 0; - Slice tmp = *contents; + absl::string_view tmp(contents->data(), contents->size()); if (OrderedCode::ReadSignedNumIncreasing(&tmp, &rawResult)) { if (rawResult >= INT32_MIN && rawResult <= INT32_MAX) { - *contents = tmp; + *contents = leveldb::Slice(tmp.data(), tmp.size()); *result = static_cast<int32_t>(rawResult); return YES; } @@ -180,10 +181,11 @@ void WriteLabeledInt32(std::string *dest, FSTComponentLabel label, int32_t value * value will be set to the decoded integer value. */ BOOL ReadLabeledInt32(Slice *contents, FSTComponentLabel expectedLabel, int32_t *value) { - Slice tmp = *contents; + absl::string_view tmp(contents->data(), contents->size()); if (ReadComponentLabelMatching(&tmp, expectedLabel)) { - if (ReadInt32(&tmp, value)) { - *contents = tmp; + Slice tmpSlice = leveldb::Slice(tmp.data(), tmp.size()); + if (ReadInt32(&tmpSlice, value)) { + *contents = tmpSlice; return YES; } } @@ -207,10 +209,10 @@ void WriteLabeledString(std::string *dest, FSTComponentLabel label, StringView v * value will be set to the decoded string value. */ BOOL ReadLabeledString(Slice *contents, FSTComponentLabel expectedLabel, std::string *value) { - Slice tmp = *contents; + absl::string_view tmp(contents->data(), contents->size()); if (ReadComponentLabelMatching(&tmp, expectedLabel)) { if (OrderedCode::ReadString(&tmp, value)) { - *contents = tmp; + *contents = leveldb::Slice(tmp.data(), tmp.size()); return YES; } } @@ -272,7 +274,7 @@ BOOL ReadDocumentKey(Slice *contents, FSTDocumentKey *__strong *result) { for (;;) { // Advance a temporary slice to avoid advancing contents into the next key component which may // not be a path segment. - Slice readPosition = completeSegments; + absl::string_view readPosition(completeSegments.data(), completeSegments.size()); if (!ReadComponentLabelMatching(&readPosition, FSTComponentLabelPathSegment)) { break; } @@ -284,7 +286,7 @@ BOOL ReadDocumentKey(Slice *contents, FSTDocumentKey *__strong *result) { [pathSegments addObject:pathSegment]; segment.clear(); - completeSegments = readPosition; + completeSegments = leveldb::Slice(readPosition.data(), readPosition.size()); } FSTResourcePath *path = [FSTResourcePath pathWithSegments:pathSegments]; @@ -304,7 +306,10 @@ inline void WriteTerminator(std::string *dest) { } inline BOOL ReadTerminator(Slice *contents) { - return ReadComponentLabelMatching(contents, FSTComponentLabelTerminator); + absl::string_view tmp(contents->data(), contents->size()); + BOOL result = ReadComponentLabelMatching(&tmp, FSTComponentLabelTerminator); + *contents = leveldb::Slice(tmp.data(), tmp.size()); + return result; } inline void WriteTableName(std::string *dest, const char *tableName) { diff --git a/Firestore/Source/Local/FSTLevelDBMutationQueue.mm b/Firestore/Source/Local/FSTLevelDBMutationQueue.mm index 74463ee..dbe58e8 100644 --- a/Firestore/Source/Local/FSTLevelDBMutationQueue.mm +++ b/Firestore/Source/Local/FSTLevelDBMutationQueue.mm @@ -34,12 +34,10 @@ #import "Firestore/Source/Model/FSTPath.h" #import "Firestore/Source/Util/FSTAssert.h" -#include "Firestore/Port/ordered_code.h" #include "Firestore/core/src/firebase/firestore/util/string_util.h" NS_ASSUME_NONNULL_BEGIN -using Firestore::OrderedCode; using Firestore::StringView; using leveldb::DB; using leveldb::Iterator; diff --git a/Firestore/Source/Local/FSTLevelDBQueryCache.mm b/Firestore/Source/Local/FSTLevelDBQueryCache.mm index 5feb9f1..46af918 100644 --- a/Firestore/Source/Local/FSTLevelDBQueryCache.mm +++ b/Firestore/Source/Local/FSTLevelDBQueryCache.mm @@ -29,11 +29,8 @@ #import "Firestore/Source/Model/FSTDocumentKey.h" #import "Firestore/Source/Util/FSTAssert.h" -#include "Firestore/Port/ordered_code.h" - NS_ASSUME_NONNULL_BEGIN -using Firestore::OrderedCode; using Firestore::StringView; using leveldb::DB; using leveldb::Iterator; diff --git a/Firestore/Source/Local/FSTLevelDBRemoteDocumentCache.mm b/Firestore/Source/Local/FSTLevelDBRemoteDocumentCache.mm index 039712c..b842cb5 100644 --- a/Firestore/Source/Local/FSTLevelDBRemoteDocumentCache.mm +++ b/Firestore/Source/Local/FSTLevelDBRemoteDocumentCache.mm @@ -32,11 +32,8 @@ #import "Firestore/Source/Model/FSTPath.h" #import "Firestore/Source/Util/FSTAssert.h" -#include "Firestore/Port/ordered_code.h" - NS_ASSUME_NONNULL_BEGIN -using Firestore::OrderedCode; using leveldb::DB; using leveldb::Iterator; using leveldb::ReadOptions; diff --git a/Firestore/Source/Local/FSTWriteGroup.mm b/Firestore/Source/Local/FSTWriteGroup.mm index 6859d53..80d09ca 100644 --- a/Firestore/Source/Local/FSTWriteGroup.mm +++ b/Firestore/Source/Local/FSTWriteGroup.mm @@ -23,9 +23,6 @@ #import "Firestore/Source/Local/FSTLevelDBKey.h" #import "Firestore/Source/Util/FSTAssert.h" -#include "Firestore/Port/ordered_code.h" - -using Firestore::OrderedCode; using Firestore::StringView; using leveldb::DB; using leveldb::Slice; diff --git a/Firestore/Source/Local/StringView.h b/Firestore/Source/Local/StringView.h index b81b7b5..8156193 100644 --- a/Firestore/Source/Local/StringView.h +++ b/Firestore/Source/Local/StringView.h @@ -25,6 +25,7 @@ #include <leveldb/slice.h> #include <string> +#include "absl/strings/string_view.h" namespace Firestore { @@ -64,6 +65,10 @@ class StringView { StringView(leveldb::Slice slice) : data_(slice.data()), size_(slice.size()) { } + // Creates a StringView from the absl::string_view. + StringView(absl::string_view s) : data_(s.data()), size_(s.size()) { + } + // Creates a StringView from the given std::string. The string must be an // lvalue for the lifetime requirements to be satisfied. StringView(const std::string &str) : data_(str.data()), size_(str.size()) { @@ -76,6 +81,13 @@ class StringView { return leveldb::Slice(data_, size_); } + // Converts this StringView to a absl::string_view, which is an equivalent (and more + // functional) type. The returned string_view has the same lifetime as this + // StringView. + operator absl::string_view() { + return absl::string_view(data_, size_); + } + private: const char *data_; const size_t size_; diff --git a/Firestore/core/src/firebase/firestore/util/CMakeLists.txt b/Firestore/core/src/firebase/firestore/util/CMakeLists.txt index 51621a0..b763a63 100644 --- a/Firestore/core/src/firebase/firestore/util/CMakeLists.txt +++ b/Firestore/core/src/firebase/firestore/util/CMakeLists.txt @@ -107,11 +107,15 @@ cc_library( SOURCES autoid.cc autoid.h + bits.cc + bits.h comparison.cc comparison.h config.h firebase_assert.h log.h + ordered_code.cc + ordered_code.h secure_random.h string_util.cc string_util.h diff --git a/Firestore/Port/bits.cc b/Firestore/core/src/firebase/firestore/util/bits.cc index 3e61223..0bfe4c3 100644 --- a/Firestore/Port/bits.cc +++ b/Firestore/core/src/firebase/firestore/util/bits.cc @@ -14,11 +14,13 @@ * limitations under the License. */ -#include "Firestore/Port/bits.h" +#include "Firestore/core/src/firebase/firestore/util/bits.h" -#include <assert.h> +#include "Firestore/core/src/firebase/firestore/util/firebase_assert.h" -namespace Firestore { +namespace firebase { +namespace firestore { +namespace util { int Bits::Log2Floor_Portable(uint32_t n) { if (n == 0) return -1; @@ -32,8 +34,10 @@ int Bits::Log2Floor_Portable(uint32_t n) { log += shift; } } - assert(value == 1); + FIREBASE_ASSERT(value == 1); return log; } -} // namespace Firestore +} // namespace util +} // namespace firestore +} // namespace firebase diff --git a/Firestore/Port/bits.h b/Firestore/core/src/firebase/firestore/util/bits.h index d212bf8..185273f 100644 --- a/Firestore/Port/bits.h +++ b/Firestore/core/src/firebase/firestore/util/bits.h @@ -14,8 +14,8 @@ * limitations under the License. */ -#ifndef IPHONE_FIRESTORE_PORT_BITS_H_ -#define IPHONE_FIRESTORE_PORT_BITS_H_ +#ifndef FIRESTORE_CORE_SRC_FIREBASE_FIRESTORE_UTIL_BITS_H_ +#define FIRESTORE_CORE_SRC_FIREBASE_FIRESTORE_UTIL_BITS_H_ // Various bit-twiddling functions, all of which are static members of the Bits // class (making it effectively a namespace). Operands are unsigned integers. @@ -27,16 +27,20 @@ class Bits_Port32_Test; class Bits_Port64_Test; -namespace Firestore { +namespace firebase { +namespace firestore { +namespace util { class Bits { public: - // Return floor(log2(n)) for positive integer n. Returns -1 iff n == 0. + /** Return floor(log2(n)) for positive integer n. Returns -1 iff n == 0. */ static int Log2Floor(uint32_t n); static int Log2Floor64(uint64_t n); - // Potentially faster version of Log2Floor() that returns an - // undefined value if n == 0 + /** + * Potentially faster version of Log2Floor() that returns an + * undefined value if n == 0. + */ static int Log2FloorNonZero(uint32_t n); static int Log2FloorNonZero64(uint64_t n); @@ -51,8 +55,8 @@ class Bits { void operator=(Bits const&) = delete; // Allow tests to call _Portable variants directly. - friend class ::Bits_Port32_Test; - friend class ::Bits_Port64_Test; + friend class Bits_Port32_Test; + friend class Bits_Port64_Test; }; // ------------------------------------------------------------------------ @@ -155,6 +159,8 @@ inline int Bits::Log2FloorNonZero64_Portable(uint64_t n) { } } -} // namespace Firestore +} // namespace util +} // namespace firestore +} // namespace firebase -#endif // IPHONE_FIRESTORE_PORT_BITS_H_ +#endif // FIRESTORE_CORE_SRC_FIREBASE_FIRESTORE_UTIL_BITS_H_ diff --git a/Firestore/Port/ordered_code.cc b/Firestore/core/src/firebase/firestore/util/ordered_code.cc index 05a1569..688f15c 100644 --- a/Firestore/Port/ordered_code.cc +++ b/Firestore/core/src/firebase/firestore/util/ordered_code.cc @@ -14,16 +14,14 @@ * limitations under the License. */ -#include "Firestore/Port/ordered_code.h" - -#include <assert.h> +#include "Firestore/core/src/firebase/firestore/util/ordered_code.h" #include <absl/base/internal/endian.h> #include <absl/base/internal/unaligned_access.h> #include <absl/base/port.h> -#include <leveldb/db.h> // For Slice -#include "Firestore/Port/bits.h" +#include "Firestore/core/src/firebase/firestore/util/bits.h" +#include "Firestore/core/src/firebase/firestore/util/firebase_assert.h" #define UNALIGNED_LOAD32 ABSL_INTERNAL_UNALIGNED_LOAD32 #define UNALIGNED_LOAD64 ABSL_INTERNAL_UNALIGNED_LOAD64 @@ -65,9 +63,9 @@ // turn is the same as the ordering of the encodings of those two // characters. Moreover, for every finite string x, F(x) < F(<infinity>). -namespace Firestore { - -using leveldb::Slice; +namespace firebase { +namespace firestore { +namespace util { static const char kEscape1 = '\000'; static const char kNullCharacter = '\xff'; // Combined with kEscape1 @@ -79,50 +77,57 @@ static const char kFFCharacter = '\000'; // Combined with kEscape2 static const char kEscape1_Separator[2] = {kEscape1, kSeparator}; -// Append to "*dest" the "len" bytes starting from "*src". +/** Append to "*dest" the "len" bytes starting from "*src". */ inline static void AppendBytes(std::string* dest, const char* src, size_t len) { dest->append(src, len); } -inline bool IsSpecialByte(char c) { return ((unsigned char)(c + 1)) < 2; } +inline static bool IsSpecialByte(char c) { + return ((unsigned char)(c + 1)) < 2; +} -// Returns 0 if one or more of the bytes in the specified uint32 value -// are the special values 0 or 255, and returns 4 otherwise. The -// result of this routine can be added to "p" to either advance past -// the next 4 bytes if they do not contain a special byte, or to -// remain on this set of four bytes if they contain the next special -// byte occurrence. -// -// REQUIRES: v is the value of loading the next 4 bytes from "*p" (we -// pass in v rather than loading it because in some cases, the client -// may already have the value in a register: "p" is just used for -// assertion checking). -inline int AdvanceIfNoSpecialBytes(uint32_t v_32, const char* p) { - assert(UNALIGNED_LOAD32(p) == v_32); +/** + * Returns 0 if one or more of the bytes in the specified uint32 value + * are the special values 0 or 255, and returns 4 otherwise. The + * result of this routine can be added to "p" to either advance past + * the next 4 bytes if they do not contain a special byte, or to + * remain on this set of four bytes if they contain the next special + * byte occurrence. + * + * REQUIRES: v_32 is the value of loading the next 4 bytes from "*p" (we + * pass in v_32 rather than loading it because in some cases, the client + * may already have the value in a register: "p" is just used for + * assertion checking). + */ +inline static int AdvanceIfNoSpecialBytes(uint32_t v_32, const char* p) { + FIREBASE_ASSERT(UNALIGNED_LOAD32(p) == v_32); // See comments in SkipToNextSpecialByte if you wish to // understand this expression (which checks for the occurrence // of the special byte values 0 or 255 in any of the bytes of v_32). if ((v_32 - 0x01010101u) & ~(v_32 + 0x01010101u) & 0x80808080u) { // Special byte is in p[0..3] - assert(IsSpecialByte(p[0]) || IsSpecialByte(p[1]) || IsSpecialByte(p[2]) || - IsSpecialByte(p[3])); + FIREBASE_ASSERT(IsSpecialByte(p[0]) || IsSpecialByte(p[1]) || + IsSpecialByte(p[2]) || IsSpecialByte(p[3])); return 0; } else { - assert(!IsSpecialByte(p[0])); - assert(!IsSpecialByte(p[1])); - assert(!IsSpecialByte(p[2])); - assert(!IsSpecialByte(p[3])); + FIREBASE_ASSERT(!IsSpecialByte(p[0])); + FIREBASE_ASSERT(!IsSpecialByte(p[1])); + FIREBASE_ASSERT(!IsSpecialByte(p[2])); + FIREBASE_ASSERT(!IsSpecialByte(p[3])); return 4; } } -// Return a pointer to the first byte in the range "[start..limit)" -// whose value is 0 or 255 (kEscape1 or kEscape2). If no such byte -// exists in the range, returns "limit". -inline const char* SkipToNextSpecialByte(const char* start, const char* limit) { +/** + * Return a pointer to the first byte in the range "[start..limit)" + * whose value is 0 or 255 (kEscape1 or kEscape2). If no such byte + * exists in the range, returns "limit". + */ +inline static const char* SkipToNextSpecialByte(const char* start, + const char* limit) { // If these constants were ever changed, this routine needs to change - assert(kEscape1 == 0); - assert((kEscape2 & 0xffu) == 255u); + FIREBASE_ASSERT(kEscape1 == 0); + FIREBASE_ASSERT((kEscape2 & 0xff) == 255); const char* p = start; while (p + 8 <= limit) { // Find out if any of the next 8 bytes are either 0 or 255 (our @@ -160,7 +165,8 @@ inline const char* SkipToNextSpecialByte(const char* start, const char* limit) { if (IsSpecialByte(p[0])) return p; if (IsSpecialByte(p[1])) return p + 1; if (IsSpecialByte(p[2])) return p + 2; - assert(IsSpecialByte(p[3])); // Last byte must be the special one + FIREBASE_ASSERT( + IsSpecialByte(p[3])); // Last byte must be the special one return p + 3; } } @@ -180,9 +186,12 @@ const char* OrderedCode::TEST_SkipToNextSpecialByte(const char* start, return SkipToNextSpecialByte(start, limit); } -// Helper routine to encode "s" and append to "*dest", escaping special -// characters. -inline static void EncodeStringFragment(std::string* dest, Slice s) { +/** + * Helper routine to encode "s" and append to "*dest", escaping special + * characters. + */ +inline static void EncodeStringFragment(std::string* dest, + absl::string_view s) { const char* p = s.data(); const char* limit = p + s.size(); const char* copy_start = p; @@ -190,44 +199,49 @@ inline static void EncodeStringFragment(std::string* dest, Slice s) { p = SkipToNextSpecialByte(p, limit); if (p >= limit) break; // No more special characters that need escaping char c = *(p++); - assert(IsSpecialByte(c)); + FIREBASE_ASSERT(IsSpecialByte(c)); if (c == kEscape1) { - AppendBytes(dest, copy_start, p - copy_start - 1); + AppendBytes(dest, copy_start, static_cast<size_t>(p - copy_start) - 1); dest->push_back(kEscape1); dest->push_back(kNullCharacter); copy_start = p; } else { - assert(c == kEscape2); - AppendBytes(dest, copy_start, p - copy_start - 1); + FIREBASE_ASSERT(c == kEscape2); + AppendBytes(dest, copy_start, static_cast<size_t>(p - copy_start) - 1); dest->push_back(kEscape2); dest->push_back(kFFCharacter); copy_start = p; } } if (p > copy_start) { - AppendBytes(dest, copy_start, p - copy_start); + AppendBytes(dest, copy_start, static_cast<size_t>(p - copy_start)); } } -void OrderedCode::WriteString(std::string* dest, Slice s) { +void OrderedCode::WriteString(std::string* dest, absl::string_view s) { EncodeStringFragment(dest, s); AppendBytes(dest, kEscape1_Separator, 2); } -// Return number of bytes needed to encode the non-length portion -// of val in ordered coding. Returns number in range [0,8]. +/** + * Return number of bytes needed to encode the non-length portion + * of val in ordered coding. Returns number in range [0,8]. + */ static inline unsigned int OrderedNumLength(uint64_t val) { const int lg = Bits::Log2Floor64(val); // -1 if val==0 return static_cast<unsigned int>(lg + 1 + 7) / 8; } -// Append n bytes from src to *dst. -// REQUIRES: n <= 9 -// REQUIRES: src[0..8] are readable bytes (even if n is smaller) -// -// If we use string::append() instead of this routine, it increases the -// runtime of WriteNumIncreasing from ~9ns to ~13ns. -static inline void AppendUpto9(std::string* dst, const char* src, +/** + * Append n bytes from src to *dst. + * REQUIRES: n <= 9 + * REQUIRES: src[0..8] are readable bytes (even if n is smaller) + * + * If we use string::append() instead of this routine, it increases the + * runtime of WriteNumIncreasing from ~9ns to ~13ns. + */ +static inline void AppendUpto9(std::string* dst, + const char* src, unsigned int n) { dst->append(src, 9); // Fixed-length append const size_t extra = 9 - n; // How many extra bytes we added @@ -244,10 +258,11 @@ void OrderedCode::WriteNumIncreasing(std::string* dest, uint64_t val) { // call on *dest. char buf[17]; - UNALIGNED_STORE64(buf + 1, absl::ghtonll(val)); // buf[0] may be needed for length + UNALIGNED_STORE64(buf + 1, + absl::ghtonll(val)); // buf[0] may be needed for length const unsigned int length = OrderedNumLength(val); char* start = buf + 9 - length - 1; - *start = length; + *start = static_cast<char>(length); AppendUpto9(dest, start, length + 1); } @@ -261,15 +276,19 @@ void OrderedCode::WriteInfinity(std::string* dest) { WriteInfinityInternal(dest); } -void OrderedCode::WriteTrailingString(std::string* dest, Slice str) { +void OrderedCode::WriteTrailingString(std::string* dest, + absl::string_view str) { dest->append(str.data(), str.size()); } -// Parse the encoding of a string previously encoded with or without -// inversion. If parse succeeds, return true, consume encoding from -// "*src", and if result != NULL append the decoded string to "*result". -// Otherwise, return false and leave both undefined. -inline static bool ReadStringInternal(Slice* src, std::string* result) { +/** + * Parse the encoding of a string previously encoded with or without + * inversion. If parse succeeds, return true, consume encoding from + * "*src", and if result != NULL append the decoded string to "*result". + * Otherwise, return false and leave both undefined. + */ +inline static bool ReadStringInternal(absl::string_view* src, + std::string* result) { const char* start = src->data(); const char* string_limit = src->data() + src->size(); @@ -284,16 +303,17 @@ inline static bool ReadStringInternal(Slice* src, std::string* result) { // If inversion is required, instead of inverting 'c', we invert the // character constants to which 'c' is compared. We get the same // behavior but save the runtime cost of inverting 'c'. - assert(IsSpecialByte(c)); + FIREBASE_ASSERT(IsSpecialByte(c)); if (c == kEscape1) { if (result) { - AppendBytes(result, copy_start, start - copy_start - 1); + AppendBytes(result, copy_start, + static_cast<size_t>(start - copy_start) - 1); } // kEscape1 kSeparator ends component // kEscape1 kNullCharacter represents '\0' const char next = *(start++); if (next == kSeparator) { - src->remove_prefix(start - src->data()); + src->remove_prefix(static_cast<size_t>(start - src->data())); return true; } else if (next == kNullCharacter) { if (result) { @@ -304,9 +324,10 @@ inline static bool ReadStringInternal(Slice* src, std::string* result) { } copy_start = start; } else { - assert(c == kEscape2); + FIREBASE_ASSERT(c == kEscape2); if (result) { - AppendBytes(result, copy_start, start - copy_start - 1); + AppendBytes(result, copy_start, + static_cast<size_t>(start - copy_start) - 1); } // kEscape2 kFFCharacter represents '\xff' // kEscape2 kInfinity is an error @@ -324,22 +345,22 @@ inline static bool ReadStringInternal(Slice* src, std::string* result) { return false; } -bool OrderedCode::ReadString(Slice* src, std::string* result) { +bool OrderedCode::ReadString(absl::string_view* src, std::string* result) { return ReadStringInternal(src, result); } -bool OrderedCode::ReadNumIncreasing(Slice* src, uint64_t* result) { +bool OrderedCode::ReadNumIncreasing(absl::string_view* src, uint64_t* result) { if (src->empty()) { return false; // Not enough bytes } // Decode length byte - const int len = static_cast<unsigned char>((*src)[0]); + const size_t len = static_cast<size_t>((*src)[0]); // If len > 0 and src is longer than 1, the first byte of "payload" // must be non-zero (otherwise the encoding is not minimal). // In opt mode, we don't enforce that encodings must be minimal. - assert(0 == len || src->size() == 1 || (*src)[1] != '\0'); + FIREBASE_ASSERT(0 == len || src->size() == 1 || (*src)[1] != '\0'); if (len + 1 > src->size() || len > 8) { return false; // Not enough bytes or too many bytes @@ -347,7 +368,7 @@ bool OrderedCode::ReadNumIncreasing(Slice* src, uint64_t* result) { if (result) { uint64_t tmp = 0; - for (int i = 0; i < len; i++) { + for (size_t i = 0; i < len; i++) { tmp <<= 8; tmp |= static_cast<unsigned char>((*src)[1 + i]); } @@ -357,7 +378,7 @@ bool OrderedCode::ReadNumIncreasing(Slice* src, uint64_t* result) { return true; } -inline static bool ReadInfinityInternal(Slice* src) { +inline static bool ReadInfinityInternal(absl::string_view* src) { if (src->size() >= 2 && ((*src)[0] == kEscape2) && ((*src)[1] == kInfinity)) { src->remove_prefix(2); return true; @@ -366,9 +387,12 @@ inline static bool ReadInfinityInternal(Slice* src) { } } -bool OrderedCode::ReadInfinity(Slice* src) { return ReadInfinityInternal(src); } +bool OrderedCode::ReadInfinity(absl::string_view* src) { + return ReadInfinityInternal(src); +} -inline static bool ReadStringOrInfinityInternal(Slice* src, std::string* result, +inline static bool ReadStringOrInfinityInternal(absl::string_view* src, + std::string* result, bool* inf) { if (ReadInfinityInternal(src)) { if (inf) *inf = true; @@ -387,12 +411,14 @@ inline static bool ReadStringOrInfinityInternal(Slice* src, std::string* result, } } -bool OrderedCode::ReadStringOrInfinity(Slice* src, std::string* result, +bool OrderedCode::ReadStringOrInfinity(absl::string_view* src, + std::string* result, bool* inf) { return ReadStringOrInfinityInternal(src, result, inf); } -bool OrderedCode::ReadTrailingString(Slice* src, std::string* result) { +bool OrderedCode::ReadTrailingString(absl::string_view* src, + std::string* result) { if (result) result->assign(src->data(), src->size()); src->remove_prefix(src->size()); return true; @@ -400,7 +426,7 @@ bool OrderedCode::ReadTrailingString(Slice* src, std::string* result) { void OrderedCode::TEST_Corrupt(std::string* str, int k) { int seen_seps = 0; - for (int i = 0; i < str->size() - 1; i++) { + for (size_t i = 0; i < str->size() - 1; i++) { if ((*str)[i] == kEscape1 && (*str)[i + 1] == kSeparator) { seen_seps++; if (seen_seps == k) { @@ -506,61 +532,70 @@ static const int8_t kBitsToLength[1 + 63] = { 4, 4, 4, 4, 4, 4, 5, 5, 5, 5, 5, 5, 5, 6, 6, 6, 6, 6, 6, 6, 7, 7, 7, 7, 7, 7, 7, 8, 8, 8, 8, 8, 8, 8, 9, 9, 9, 9, 9, 9, 9, 10}; -// Calculates the encoding length in bytes of the signed number n. +/** Calculates the encoding length in bytes of the signed number n. */ static inline int SignedEncodingLength(int64_t n) { - return kBitsToLength[Bits::Log2Floor64(n < 0 ? ~n : n) + 1]; + return kBitsToLength[Bits::Log2Floor64( + static_cast<uint64_t>(n < 0 ? ~n : n)) + + 1]; } -// Slightly faster version for n > 0. +/** Slightly faster version for n > 0. */ static inline int SignedEncodingLengthPositive(int64_t n) { - return kBitsToLength[Bits::Log2FloorNonZero64(n) + 1]; + return kBitsToLength[Bits::Log2FloorNonZero64(static_cast<uint64_t>(n)) + 1]; } void OrderedCode::WriteSignedNumIncreasing(std::string* dest, int64_t val) { - const uint64_t x = val < 0 ? ~val : val; + const int64_t x = val < 0 ? ~val : val; if (x < 64) { // fast path for encoding length == 1 - *dest += kLengthToHeaderBits[1][0] ^ val; + *dest += static_cast<char>(kLengthToHeaderBits[1][0] ^ val); return; } // buf = val in network byte order, sign extended to 10 bytes const char sign_byte = val < 0 ? '\xff' : '\0'; char buf[10] = { - sign_byte, sign_byte, + sign_byte, + sign_byte, }; - UNALIGNED_STORE64(buf + 2, absl::ghtonll(val)); + UNALIGNED_STORE64(buf + 2, absl::ghtonll(static_cast<uint64_t>(val))); - static_assert(sizeof(buf) == kMaxSigned64Length, "max length size mismatch"); - const int len = SignedEncodingLengthPositive(x); - assert(len >= 2); + FIREBASE_ASSERT_MESSAGE_WITH_EXPRESSION(sizeof(buf) == kMaxSigned64Length, + sizeof(buf) == kMaxSigned64Length, + "max length size mismatch"); + const size_t len = static_cast<size_t>(SignedEncodingLengthPositive(x)); + FIREBASE_ASSERT(len >= 2); char* const begin = buf + sizeof(buf) - len; begin[0] ^= kLengthToHeaderBits[len][0]; begin[1] ^= kLengthToHeaderBits[len][1]; // ok because len >= 2 dest->append(begin, len); } -bool OrderedCode::ReadSignedNumIncreasing(Slice* src, int64_t* result) { +bool OrderedCode::ReadSignedNumIncreasing(absl::string_view* src, + int64_t* result) { if (src->empty()) return false; const uint64_t xor_mask = (!((*src)[0] & 0x80)) ? ~0ULL : 0ULL; - const unsigned char first_byte = (*src)[0] ^ (xor_mask & 0xff); + const unsigned char first_byte = static_cast<unsigned char>( + static_cast<uint64_t>((*src)[0]) ^ (xor_mask & 0xff)); // now calculate and test length, and set x to raw (unmasked) result - int len; + size_t len; uint64_t x; if (first_byte != 0xff) { - len = 7 - Bits::Log2FloorNonZero(first_byte ^ 0xff); + len = static_cast<size_t>(7 - Bits::Log2FloorNonZero(first_byte ^ 0xff)); if (src->size() < len) return false; x = xor_mask; // sign extend using xor_mask - for (int i = 0; i < len; ++i) + for (size_t i = 0; i < len; ++i) x = (x << 8) | static_cast<unsigned char>((*src)[i]); } else { len = 8; if (src->size() < len) return false; - const unsigned char second_byte = (*src)[1] ^ (xor_mask & 0xff); + const unsigned char second_byte = static_cast<unsigned char>( + static_cast<uint64_t>((*src)[1]) ^ (xor_mask & 0xff)); if (second_byte >= 0x80) { if (second_byte < 0xc0) { len = 9; } else { - const unsigned char third_byte = (*src)[2] ^ (xor_mask & 0xff); + const unsigned char third_byte = static_cast<unsigned char>( + static_cast<uint64_t>((*src)[2]) ^ (xor_mask & 0xff)); if (second_byte == 0xc0 && third_byte < 0x80) { len = 10; } else { @@ -574,12 +609,14 @@ bool OrderedCode::ReadSignedNumIncreasing(Slice* src, int64_t* result) { x ^= kLengthToMask[len]; // remove spurious header bits - assert(len == SignedEncodingLength(x)); + FIREBASE_ASSERT(len == static_cast<size_t>( + SignedEncodingLength(static_cast<int64_t>(x)))); - if (result) *result = x; - src->remove_prefix(len); + if (result) *result = static_cast<int64_t>(x); + src->remove_prefix(static_cast<size_t>(len)); return true; } -} // namespace Firestore - +} // namespace util +} // namespace firestore +} // namespace firebase diff --git a/Firestore/Port/ordered_code.h b/Firestore/core/src/firebase/firestore/util/ordered_code.h index 7c390a5..57b84bd 100644 --- a/Firestore/Port/ordered_code.h +++ b/Firestore/core/src/firebase/firestore/util/ordered_code.h @@ -36,16 +36,16 @@ // This module is often useful when generating multi-part sstable // keys that have to be ordered in a particular fashion. -#ifndef IPHONE_FIRESTORE_PORT_ORDERED_CODE_H_ -#define IPHONE_FIRESTORE_PORT_ORDERED_CODE_H_ +#ifndef FIRESTORE_CORE_SRC_FIREBASE_FIRESTORE_UTIL_ORDERED_CODE_H_ +#define FIRESTORE_CORE_SRC_FIREBASE_FIRESTORE_UTIL_ORDERED_CODE_H_ #include <string> -namespace leveldb { -class Slice; -} +#include "absl/strings/string_view.h" -namespace Firestore { +namespace firebase { +namespace firestore { +namespace util { class OrderedCode { public: @@ -60,19 +60,23 @@ class OrderedCode { // is not called WriteStringIncreasing() for convenience and backward // compatibility. - static void WriteString(std::string* dest, leveldb::Slice str); + static void WriteString(std::string* dest, absl::string_view str); static void WriteNumIncreasing(std::string* dest, uint64_t num); static void WriteSignedNumIncreasing(std::string* dest, int64_t num); - // Creates an encoding for the "infinite string", a value considered to - // be lexicographically after any real string. Note that in the case of - // WriteInfinityDecreasing(), this would come before any real string as - // the ordering puts lexicographically greater values first. + /** + * Creates an encoding for the "infinite string", a value considered to + * be lexicographically after any real string. Note that in the case of + * WriteInfinityDecreasing(), this would come before any real string as + * the ordering puts lexicographically greater values first. + */ static void WriteInfinity(std::string* dest); - // Special string append that can only be used at the tail end of - // an encoded string -- blindly appends "str" to "*dest". - static void WriteTrailingString(std::string* dest, leveldb::Slice str); + /** + * Special string append that can only be used at the tail end of + * an encoded string -- blindly appends "str" to "*dest". + */ + static void WriteTrailingString(std::string* dest, absl::string_view str); // ------------------------------------------------------------------- // Decoding routines: these extract an item earlier encoded using @@ -83,26 +87,33 @@ class OrderedCode { // "*result". Returns true if the next item was read successfully, false // otherwise. - static bool ReadString(leveldb::Slice* src, std::string* result); - static bool ReadNumIncreasing(leveldb::Slice* src, uint64_t* result); - static bool ReadSignedNumIncreasing(leveldb::Slice* src, int64_t* result); + static bool ReadString(absl::string_view* src, std::string* result); + static bool ReadNumIncreasing(absl::string_view* src, uint64_t* result); + static bool ReadSignedNumIncreasing(absl::string_view* src, int64_t* result); - static bool ReadInfinity(leveldb::Slice* src); - static bool ReadTrailingString(leveldb::Slice* src, std::string* result); + static bool ReadInfinity(absl::string_view* src); + static bool ReadTrailingString(absl::string_view* src, std::string* result); - // REQUIRES: next item was encoded by WriteInfinity() or WriteString() - static bool ReadStringOrInfinity(leveldb::Slice* src, std::string* result, bool* inf); + /** REQUIRES: next item was encoded by WriteInfinity() or WriteString(). */ + static bool ReadStringOrInfinity(absl::string_view* src, + std::string* result, + bool* inf); - // Helper for testing: corrupt "*str" by changing the kth item separator - // in the string. + /** + * Helper for testing: corrupt "*str" by changing the kth item separator + * in the string. + */ static void TEST_Corrupt(std::string* str, int k); - // Helper for testing. - // SkipToNextSpecialByte is an internal routine defined in the .cc file - // with the following semantics. Return a pointer to the first byte - // in the range "[start..limit)" whose value is 0 or 255. If no such - // byte exists in the range, returns "limit". - static const char* TEST_SkipToNextSpecialByte(const char* start, const char* limit); + /** + * Helper for testing. + * SkipToNextSpecialByte is an internal routine defined in the .cc file + * with the following semantics. Return a pointer to the first byte + * in the range "[start..limit)" whose value is 0 or 255. If no such + * byte exists in the range, returns "limit". + */ + static const char* TEST_SkipToNextSpecialByte(const char* start, + const char* limit); // Not an instantiable class, but the class exists to make it easy to // use with a single using statement. @@ -111,6 +122,8 @@ class OrderedCode { OrderedCode& operator=(const OrderedCode&) = delete; }; -} // namespace Firestore +} // namespace util +} // namespace firestore +} // namespace firebase -#endif // IPHONE_FIRESTORE_PORT_ORDERED_CODE_H_ +#endif // FIRESTORE_CORE_SRC_FIREBASE_FIRESTORE_UTIL_ORDERED_CODE_H_ diff --git a/Firestore/core/src/firebase/firestore/util/secure_random.h b/Firestore/core/src/firebase/firestore/util/secure_random.h index 72be1bd..95b41e1 100644 --- a/Firestore/core/src/firebase/firestore/util/secure_random.h +++ b/Firestore/core/src/firebase/firestore/util/secure_random.h @@ -50,6 +50,22 @@ class SecureRandom { } result_type operator()(); + + /** Returns a uniformly distributed pseudorandom integer in [0, n). */ + inline result_type Uniform(result_type n) { + // Divides the range into buckets of size n plus leftovers. + const result_type rem = (max() - min()) % n + min() + 1; + result_type rnd; + // Generates random number until the number falls into a bucket. + do { + rnd = (*this)(); + } while (rnd < rem); + return rnd % n; + } + + inline bool OneIn(result_type n) { + return Uniform(n) == 0; + } }; } // namespace util diff --git a/Firestore/core/test/firebase/firestore/util/CMakeLists.txt b/Firestore/core/test/firebase/firestore/util/CMakeLists.txt index 13a2e46..eb5a898 100644 --- a/Firestore/core/test/firebase/firestore/util/CMakeLists.txt +++ b/Firestore/core/test/firebase/firestore/util/CMakeLists.txt @@ -36,7 +36,9 @@ cc_test( firebase_firestore_util_test SOURCES autoid_test.cc + bits_test.cc comparison_test.cc + ordered_code_test.cc string_printf_test.cc string_util_test.cc DEPENDS diff --git a/Firestore/Port/bits_test.cc b/Firestore/core/test/firebase/firestore/util/bits_test.cc index 8c3c246..cb0976b 100644 --- a/Firestore/Port/bits_test.cc +++ b/Firestore/core/test/firebase/firestore/util/bits_test.cc @@ -14,24 +14,24 @@ * limitations under the License. */ -#include "Firestore/Port/bits.h" +#include "Firestore/core/src/firebase/firestore/util/bits.h" +#include <algorithm> #include <iostream> +#include <limits> -#include "base/commandlineflags.h" -#include "testing/base/public/gunit.h" -#include "util/random/mt_random.h" +#include "Firestore/core/src/firebase/firestore/util/secure_random.h" +#include "gtest/gtest.h" -using Firestore::Bits; +namespace firebase { +namespace firestore { +namespace util { -DEFINE_int32(num_iterations, 10000, "Number of test iterations to run."); +const int kNumIterations = 10000; // "Number of test iterations to run. class BitsTest : public testing::Test { - public: - BitsTest() : random_(testing::FLAGS_gunit_random_seed) {} - protected: - MTRandom random_; + SecureRandom random_; }; TEST_F(BitsTest, Log2EdgeCases) { @@ -41,7 +41,7 @@ TEST_F(BitsTest, Log2EdgeCases) { EXPECT_EQ(-1, Bits::Log2Floor64(0)); for (int i = 0; i < 32; i++) { - uint32 n = 1U << i; + uint32_t n = 1U << i; EXPECT_EQ(i, Bits::Log2Floor(n)); EXPECT_EQ(i, Bits::Log2FloorNonZero(n)); if (n > 2) { @@ -53,7 +53,7 @@ TEST_F(BitsTest, Log2EdgeCases) { } for (int i = 0; i < 64; i++) { - uint64 n = 1ULL << i; + uint64_t n = 1ULL << i; EXPECT_EQ(i, Bits::Log2Floor64(n)); EXPECT_EQ(i, Bits::Log2FloorNonZero64(n)); if (n > 2) { @@ -68,11 +68,11 @@ TEST_F(BitsTest, Log2EdgeCases) { TEST_F(BitsTest, Log2Random) { std::cout << "TestLog2Random" << std::endl; - for (int i = 0; i < FLAGS_num_iterations; i++) { + for (int i = 0; i < kNumIterations; i++) { int maxbit = -1; - uint32 n = 0; - while (!random_.OneIn(32)) { - int bit = random_.Uniform(32); + uint32_t n = 0; + while (!random_.OneIn(32u)) { + int bit = static_cast<int>(random_.Uniform(32u)); n |= (1U << bit); maxbit = std::max(bit, maxbit); } @@ -86,11 +86,11 @@ TEST_F(BitsTest, Log2Random) { TEST_F(BitsTest, Log2Random64) { std::cout << "TestLog2Random64" << std::endl; - for (int i = 0; i < FLAGS_num_iterations; i++) { + for (int i = 0; i < kNumIterations; i++) { int maxbit = -1; - uint64 n = 0; - while (!random_.OneIn(64)) { - int bit = random_.Uniform(64); + uint64_t n = 0; + while (!random_.OneIn(64u)) { + int bit = static_cast<int>(random_.Uniform(64u)); n |= (1ULL << bit); maxbit = std::max(bit, maxbit); } @@ -103,8 +103,8 @@ TEST_F(BitsTest, Log2Random64) { TEST(Bits, Port32) { for (int shift = 0; shift < 32; shift++) { - for (int delta = -1; delta <= +1; delta++) { - const uint32 v = (static_cast<uint32>(1) << shift) + delta; + for (uint32_t delta = 0; delta <= 2; delta++) { + const uint32_t v = (static_cast<uint32_t>(1) << shift) - 1 + delta; EXPECT_EQ(Bits::Log2Floor_Portable(v), Bits::Log2Floor(v)) << v; if (v != 0) { EXPECT_EQ(Bits::Log2FloorNonZero_Portable(v), Bits::Log2FloorNonZero(v)) @@ -112,7 +112,7 @@ TEST(Bits, Port32) { } } } - static const uint32 M32 = kuint32max; + static const uint32_t M32 = std::numeric_limits<uint32_t>::max(); EXPECT_EQ(Bits::Log2Floor_Portable(M32), Bits::Log2Floor(M32)) << M32; EXPECT_EQ(Bits::Log2FloorNonZero_Portable(M32), Bits::Log2FloorNonZero(M32)) << M32; @@ -120,8 +120,8 @@ TEST(Bits, Port32) { TEST(Bits, Port64) { for (int shift = 0; shift < 64; shift++) { - for (int delta = -1; delta <= +1; delta++) { - const uint64 v = (static_cast<uint64>(1) << shift) + delta; + for (uint64_t delta = 0; delta <= 2; delta++) { + const uint64_t v = (static_cast<uint64_t>(1) << shift) - 1 + delta; EXPECT_EQ(Bits::Log2Floor64_Portable(v), Bits::Log2Floor64(v)) << v; if (v != 0) { EXPECT_EQ(Bits::Log2FloorNonZero64_Portable(v), @@ -130,9 +130,13 @@ TEST(Bits, Port64) { } } } - static const uint64 M64 = kuint64max; + static const uint64_t M64 = std::numeric_limits<uint64_t>::max(); EXPECT_EQ(Bits::Log2Floor64_Portable(M64), Bits::Log2Floor64(M64)) << M64; EXPECT_EQ(Bits::Log2FloorNonZero64_Portable(M64), Bits::Log2FloorNonZero64(M64)) << M64; } + +} // namespace util +} // namespace firestore +} // namespace firebase diff --git a/Firestore/Port/ordered_code_test.cc b/Firestore/core/test/firebase/firestore/util/ordered_code_test.cc index 0a339fc..fd2ce83 100644 --- a/Firestore/Port/ordered_code_test.cc +++ b/Firestore/core/test/firebase/firestore/util/ordered_code_test.cc @@ -14,63 +14,22 @@ * limitations under the License. */ -#include "Firestore/Port/ordered_code.h" +#include "Firestore/core/src/firebase/firestore/util/ordered_code.h" -// #include <float.h> -// #include <stddef.h> #include <iostream> #include <limits> -#include "base/logging.h" -#include "testing/base/public/gunit.h" -#include <leveldb/db.h> -#include "util/random/acmrandom.h" - -using Firestore::OrderedCode; -using leveldb::Slice; - -// Make Slices writeable to ostream, making all the CHECKs happy below. -namespace { -void WritePadding(std::ostream& o, size_t pad) { - char fill_buf[32]; - memset(fill_buf, o.fill(), sizeof(fill_buf)); - while (pad) { - size_t n = std::min(pad, sizeof(fill_buf)); - o.write(fill_buf, n); - pad -= n; - } -} -} // namespace - -namespace leveldb { - -std::ostream& operator<<(std::ostream& o, const Slice slice) { - std::ostream::sentry sentry(o); - if (sentry) { - size_t lpad = 0; - size_t rpad = 0; - if (o.width() > slice.size()) { - size_t pad = o.width() - slice.size(); - if ((o.flags() & o.adjustfield) == o.left) { - rpad = pad; - } else { - lpad = pad; - } - } - if (lpad) WritePadding(o, lpad); - o.write(slice.data(), slice.size()); - if (rpad) WritePadding(o, rpad); - o.width(0); - } - return o; -} +#include "Firestore/core/src/firebase/firestore/util/secure_random.h" +#include "gtest/gtest.h" -} // namespace leveldb +namespace firebase { +namespace firestore { +namespace util { -static std::string RandomString(ACMRandom* rnd, int len) { +static std::string RandomString(SecureRandom* rnd, int len) { std::string x; for (int i = 0; i < len; i++) { - x += rnd->Uniform(256); + x += static_cast<char>(rnd->Uniform(256)); } return x; } @@ -82,7 +41,7 @@ static std::string RandomString(ACMRandom* rnd, int len) { template <typename T> static void OCWriteIncreasing(std::string* dest, const T& val); template <typename T> -static bool OCReadIncreasing(Slice* src, T* result); +static bool OCReadIncreasing(absl::string_view* src, T* result); // Read/WriteIncreasing<std::string> template <> @@ -90,7 +49,8 @@ void OCWriteIncreasing<std::string>(std::string* dest, const std::string& val) { OrderedCode::WriteString(dest, val); } template <> -bool OCReadIncreasing<std::string>(Slice* src, std::string* result) { +bool OCReadIncreasing<std::string>(absl::string_view* src, + std::string* result) { return OrderedCode::ReadString(src, result); } @@ -100,7 +60,7 @@ void OCWriteIncreasing<uint64_t>(std::string* dest, const uint64_t& val) { OrderedCode::WriteNumIncreasing(dest, val); } template <> -bool OCReadIncreasing<uint64_t>(Slice* src, uint64_t* result) { +bool OCReadIncreasing<uint64_t>(absl::string_view* src, uint64_t* result) { return OrderedCode::ReadNumIncreasing(src, result); } @@ -112,12 +72,13 @@ void OCWriteIncreasing<int64_t>(std::string* dest, const int64_t& val) { OrderedCode::WriteSignedNumIncreasing(dest, val); } template <> -bool OCReadIncreasing<int64_t>(Slice* src, int64_t* result) { +bool OCReadIncreasing<int64_t>(absl::string_view* src, int64_t* result) { return OrderedCode::ReadSignedNumIncreasing(src, result); } template <typename T> std::string OCWrite(T val, Direction direction) { + EXPECT_EQ(INCREASING, direction); // DECREASING never implemented. std::string result; OCWriteIncreasing<T>(&result, val); return result; @@ -125,11 +86,13 @@ std::string OCWrite(T val, Direction direction) { template <typename T> void OCWriteToString(std::string* result, T val, Direction direction) { + EXPECT_EQ(INCREASING, direction); // DECREASING never implemented. OCWriteIncreasing<T>(result, val); } template <typename T> -bool OCRead(Slice* s, T* val, Direction direction) { +bool OCRead(absl::string_view* s, T* val, Direction direction) { + EXPECT_EQ(INCREASING, direction); // DECREASING never implemented. return OCReadIncreasing<T>(s, val); } @@ -139,16 +102,16 @@ bool OCRead(Slice* s, T* val, Direction direction) { template <typename T> static T TestRead(Direction d, const std::string& a) { // gracefully reject any proper prefix of an encoding - for (int i = 0; i < a.size() - 1; ++i) { - Slice s(a.data(), i); - CHECK(!OCRead<T>(&s, NULL, d)); - CHECK_EQ(s, a.substr(0, i)); + for (size_t i = 0; i < a.size() - 1; ++i) { + absl::string_view s(a.data(), i); + EXPECT_TRUE(!OCRead<T>(&s, NULL, d)); + EXPECT_EQ(s, a.substr(0, i)); } - Slice s(a); + absl::string_view s(a); T v; - CHECK(OCRead<T>(&s, &v, d)); - CHECK(s.empty()); + EXPECT_TRUE(OCRead<T>(&s, &v, d)); + EXPECT_TRUE(s.empty()); return v; } @@ -166,12 +129,13 @@ static void TestWriteAppends(Direction d, T first, U second) { std::string encoded_first_only = encoded; OCWriteToString<U>(&encoded, second, d); EXPECT_NE(encoded, encoded_first_only); - EXPECT_TRUE(Slice(encoded).starts_with(encoded_first_only)); + EXPECT_EQ(absl::string_view(encoded).substr(0, encoded_first_only.length()), + encoded_first_only); } template <typename T> static void TestNumbers(T multiplier) { - for (int j = 0; j < 2; ++j) { + for (int j = 0; j < 1; ++j) { const Direction d = static_cast<Direction>(j); // first test powers of 2 (and nearby numbers) @@ -180,19 +144,23 @@ static void TestNumbers(T multiplier) { TestWriteRead(d, multiplier * x); if (x != std::numeric_limits<T>::max()) { TestWriteRead(d, multiplier * (x + 1)); - } else if (multiplier < 0 && multiplier == -1) { + } else if (multiplier < 0 && static_cast<int64_t>(multiplier) == -1) { TestWriteRead(d, -x - 1); } } - ACMRandom rnd(301); + SecureRandom rnd; // Generate 32bit pseudo-random integer. for (int bits = 1; bits <= std::numeric_limits<T>().digits; ++bits) { // test random non-negative numbers with given number of significant bits const uint64_t mask = (~0ULL) >> (64 - bits); for (int i = 0; i < 1000; i++) { - T x = rnd.Next64() & mask; + T x = static_cast<T>((static_cast<uint64_t>(rnd()) << 32 | + static_cast<uint64_t>(rnd())) & + mask); TestWriteRead(d, multiplier * x); - T y = rnd.Next64() & mask; + T y = static_cast<T>((static_cast<uint64_t>(rnd()) << 32 | + static_cast<uint64_t>(rnd())) & + mask); TestWriteAppends(d, multiplier * x, multiplier * y); } } @@ -200,7 +168,8 @@ static void TestNumbers(T multiplier) { } // Return true iff 'a' is "before" 'b' according to 'direction' -static bool CompareStrings(const std::string& a, const std::string& b, +static bool CompareStrings(const std::string& a, + const std::string& b, Direction d) { return (INCREASING == d) ? (a < b) : (b < a); } @@ -216,12 +185,12 @@ static void TestNumberOrdering() { std::string str = OCWrite<T>(num, d); std::string strplus1 = OCWrite<T>(num + 1, d); - CHECK(CompareStrings(strminus1, str, d)); - CHECK(CompareStrings(str, strplus1, d)); + EXPECT_TRUE(CompareStrings(strminus1, str, d)); + EXPECT_TRUE(CompareStrings(str, strplus1, d)); // Compare 'str' with 'laststr'. When we approach 0, 'laststr' is // not necessarily before 'strminus1'. - CHECK(CompareStrings(laststr, str, d)); + EXPECT_TRUE(CompareStrings(laststr, str, d)); laststr = str; } @@ -234,46 +203,46 @@ static void TestNumberOrdering() { std::string str = OCWrite<T>(num, d); std::string strplus1 = OCWrite<T>(num + 1, d); - CHECK(CompareStrings(strminus1, str, d)); - CHECK(CompareStrings(str, strplus1, d)); + EXPECT_TRUE(CompareStrings(strminus1, str, d)); + EXPECT_TRUE(CompareStrings(str, strplus1, d)); // Compare 'str' with 'laststr'. - CHECK(CompareStrings(laststr, str, d)); + EXPECT_TRUE(CompareStrings(laststr, str, d)); laststr = str; } } // Helper routine for testing TEST_SkipToNextSpecialByte -static int FindSpecial(const std::string& x) { +static size_t FindSpecial(const std::string& x) { const char* p = x.data(); const char* limit = p + x.size(); const char* result = OrderedCode::TEST_SkipToNextSpecialByte(p, limit); - return result - p; + return static_cast<size_t>(result - p); } TEST(OrderedCode, SkipToNextSpecialByte) { - for (int len = 0; len < 256; len++) { - ACMRandom rnd(301); + for (size_t len = 0; len < 256; len++) { + SecureRandom rnd; std::string x; while (x.size() < len) { - char c = 1 + rnd.Uniform(254); + char c = 1 + static_cast<char>(rnd.Uniform(254)); ASSERT_NE(c, 0); ASSERT_NE(c, 255); x += c; // No 0 bytes, no 255 bytes } EXPECT_EQ(FindSpecial(x), x.size()); - for (int special_pos = 0; special_pos < len; special_pos++) { + for (size_t special_pos = 0; special_pos < len; special_pos++) { for (int special_test = 0; special_test < 2; special_test++) { - const char special_byte = (special_test == 0) ? 0 : 255; + const char special_byte = (special_test == 0) ? 0 : '\xff'; std::string y = x; y[special_pos] = special_byte; EXPECT_EQ(FindSpecial(y), special_pos); if (special_pos < 16) { // Add some special bytes after the one at special_pos to make sure // we still return the earliest special byte in the string - for (int rest = special_pos + 1; rest < len; rest++) { + for (size_t rest = special_pos + 1; rest < len; rest++) { if (rnd.OneIn(3)) { - y[rest] = rnd.OneIn(2) ? 0 : 255; + y[rest] = rnd.OneIn(2) ? 0 : '\xff'; EXPECT_EQ(FindSpecial(y), special_pos); } } @@ -297,9 +266,9 @@ TEST(OrderedCode, ExhaustiveFindSpecial) { for (int b0 = 0; b0 < 256; b0++) { for (int b1 = 0; b1 < 256; b1++) { for (int b2 = 0; b2 < 256; b2++) { - buf[start_offset + 0] = b0; - buf[start_offset + 1] = b1; - buf[start_offset + 2] = b2; + buf[start_offset + 0] = static_cast<char>(b0); + buf[start_offset + 1] = static_cast<char>(b1); + buf[start_offset + 2] = static_cast<char>(b2); char* expected; if (b0 == 0 || b0 == 255) { expected = &buf[start_offset]; @@ -320,16 +289,22 @@ TEST(OrderedCode, ExhaustiveFindSpecial) { EXPECT_EQ(count, 256 * 256 * 256 * 2); } -TEST(Uint64, EncodeDecode) { TestNumbers<uint64_t>(1); } +TEST(OrderedCodeUint64, EncodeDecode) { + TestNumbers<uint64_t>(1); +} -TEST(Uint64, Ordering) { TestNumberOrdering<uint64_t>(); } +TEST(OrderedCodeUint64, Ordering) { + TestNumberOrdering<uint64_t>(); +} -TEST(Int64, EncodeDecode) { +TEST(OrderedCodeInt64, EncodeDecode) { TestNumbers<int64_t>(1); TestNumbers<int64_t>(-1); } -TEST(Int64, Ordering) { TestNumberOrdering<int64_t>(); } +TEST(OrderedCodeInt64, Ordering) { + TestNumberOrdering<int64_t>(); +} // Returns the bitwise complement of s. static inline std::string StrNot(const std::string& s) { @@ -340,7 +315,7 @@ static inline std::string StrNot(const std::string& s) { template <typename T> static void TestInvalidEncoding(Direction d, const std::string& s) { - Slice p(s); + absl::string_view p(s); EXPECT_FALSE(OCRead<T>(&p, static_cast<T*>(NULL), d)); EXPECT_EQ(s, p); } @@ -363,22 +338,22 @@ TEST(OrderedCodeInvalidEncodingsTest, NonCanonical) { // and thus should be avoided to not mess up the string ordering of // encodings. - ACMRandom rnd(301); + SecureRandom rnd; for (int n = 2; n <= 9; ++n) { // The zero in non_minimal[1] is "redundant". std::string non_minimal = std::string(1, n - 1) + std::string(1, 0) + RandomString(&rnd, n - 2); - EXPECT_EQ(n, non_minimal.length()); + EXPECT_EQ(static_cast<size_t>(n), non_minimal.length()); EXPECT_NE(OCWrite<uint64_t>(0, INCREASING), non_minimal); - if (DEBUG_MODE) { - Slice s(non_minimal); - EXPECT_DEATH_IF_SUPPORTED(OrderedCode::ReadNumIncreasing(&s, NULL), - "ssertion failed"); - } else { - TestRead<uint64_t>(INCREASING, non_minimal); - } + +#if defined(NDEBUG) + TestRead<uint64_t>(INCREASING, non_minimal); +#else // defined(NDEBUG) + absl::string_view s(non_minimal); + EXPECT_ANY_THROW(OrderedCode::ReadNumIncreasing(&s, NULL)); +#endif // defined(NDEBUG) } for (int n = 2; n <= 10; ++n) { @@ -387,31 +362,32 @@ TEST(OrderedCodeInvalidEncodingsTest, NonCanonical) { std::string(n / 8, 0xff) + std::string(1, 0xff << (8 - (n % 8))); // There are more than 7 zero bits between header bits and "payload". std::string non_minimal = - header + std::string(1, rnd.Uniform(256) & ~*header.rbegin()) + - RandomString(&rnd, n - header.length() - 1); - EXPECT_EQ(n, non_minimal.length()); + header + + std::string(1, + static_cast<char>(rnd.Uniform(256)) & ~*header.rbegin()) + + RandomString(&rnd, n - static_cast<int>(header.length()) - 1); + EXPECT_EQ(static_cast<size_t>(n), non_minimal.length()); EXPECT_NE(OCWrite<int64_t>(0, INCREASING), non_minimal); - if (DEBUG_MODE) { - Slice s(non_minimal); - EXPECT_DEATH_IF_SUPPORTED(OrderedCode::ReadSignedNumIncreasing(&s, NULL), - "ssertion failed") - << n; - s = non_minimal; - } else { - TestRead<int64_t>(INCREASING, non_minimal); - } + +#if defined(NDEBUG) + TestRead<int64_t>(INCREASING, non_minimal); +#else // defined(NDEBUG) + absl::string_view s(non_minimal); + EXPECT_ANY_THROW(OrderedCode::ReadSignedNumIncreasing(&s, NULL)); + s = non_minimal; +#endif // defined(NDEBUG) } } // --------------------------------------------------------------------- // Strings -TEST(String, Infinity) { +TEST(OrderedCodeString, Infinity) { const std::string value("\xff\xff foo"); bool is_inf; std::string encoding, parsed; - Slice s; + absl::string_view s; // Check encoding/decoding of "infinity" for ascending order encoding.clear(); @@ -419,11 +395,11 @@ TEST(String, Infinity) { encoding.push_back('a'); s = encoding; EXPECT_TRUE(OrderedCode::ReadInfinity(&s)); - EXPECT_EQ(1, s.size()); + EXPECT_EQ(1u, s.size()); s = encoding; is_inf = false; EXPECT_TRUE(OrderedCode::ReadStringOrInfinity(&s, NULL, &is_inf)); - EXPECT_EQ(1, s.size()); + EXPECT_EQ(1u, s.size()); EXPECT_TRUE(is_inf); // Check ReadStringOrInfinity() can parse ordinary strings @@ -434,14 +410,14 @@ TEST(String, Infinity) { is_inf = false; parsed.clear(); EXPECT_TRUE(OrderedCode::ReadStringOrInfinity(&s, &parsed, &is_inf)); - EXPECT_EQ(1, s.size()); + EXPECT_EQ(1u, s.size()); EXPECT_FALSE(is_inf); EXPECT_EQ(value, parsed); } -TEST(String, EncodeDecode) { - ACMRandom rnd(301); - for (int i = 0; i < 2; ++i) { +TEST(OrderedCodeString, EncodeDecode) { + SecureRandom rnd; + for (int i = 0; i < 1; ++i) { const Direction d = static_cast<Direction>(i); for (int len = 0; len < 256; len++) { @@ -457,48 +433,48 @@ TEST(String, EncodeDecode) { OCWriteToString<std::string>(&out, b, d); std::string a2, b2, dummy; - Slice s = out; - Slice s2 = out; - CHECK(OCRead<std::string>(&s, &a2, d)); - CHECK(OCRead<std::string>(&s2, NULL, d)); - CHECK_EQ(s, s2); - - CHECK(OCRead<std::string>(&s, &b2, d)); - CHECK(OCRead<std::string>(&s2, NULL, d)); - CHECK_EQ(s, s2); - - CHECK(!OCRead<std::string>(&s, &dummy, d)); - CHECK(!OCRead<std::string>(&s2, NULL, d)); - CHECK_EQ(a, a2); - CHECK_EQ(b, b2); - CHECK(s.empty()); - CHECK(s2.empty()); + absl::string_view s = out; + absl::string_view s2 = out; + EXPECT_TRUE(OCRead<std::string>(&s, &a2, d)); + EXPECT_TRUE(OCRead<std::string>(&s2, NULL, d)); + EXPECT_EQ(s, s2); + + EXPECT_TRUE(OCRead<std::string>(&s, &b2, d)); + EXPECT_TRUE(OCRead<std::string>(&s2, NULL, d)); + EXPECT_EQ(s, s2); + + EXPECT_TRUE(!OCRead<std::string>(&s, &dummy, d)); + EXPECT_TRUE(!OCRead<std::string>(&s2, NULL, d)); + EXPECT_EQ(a, a2); + EXPECT_EQ(b, b2); + EXPECT_TRUE(s.empty()); + EXPECT_TRUE(s2.empty()); } } } } // 'str' is a static C-style string that may contain '\0' -#define STATIC_STR(str) Slice((str), sizeof(str) - 1) +#define STATIC_STR(str) absl::string_view((str), sizeof(str) - 1) -static std::string EncodeStringIncreasing(Slice value) { +static std::string EncodeStringIncreasing(absl::string_view value) { std::string encoded; OrderedCode::WriteString(&encoded, value); return encoded; } -TEST(String, Increasing) { +TEST(OrderedCodeString, Increasing) { // Here are a series of strings in non-decreasing order, including // consecutive strings such that the second one is equal to, a proper // prefix of, or has the same length as the first one. Most also contain // the special escaping characters '\x00' and '\xff'. - ASSERT_EQ(EncodeStringIncreasing(STATIC_STR("")), + EXPECT_EQ(EncodeStringIncreasing(STATIC_STR("")), EncodeStringIncreasing(STATIC_STR(""))); ASSERT_LT(EncodeStringIncreasing(STATIC_STR("")), EncodeStringIncreasing(STATIC_STR("\x00"))); - ASSERT_EQ(EncodeStringIncreasing(STATIC_STR("\x00")), + EXPECT_EQ(EncodeStringIncreasing(STATIC_STR("\x00")), EncodeStringIncreasing(STATIC_STR("\x00"))); ASSERT_LT(EncodeStringIncreasing(STATIC_STR("\x00")), @@ -507,7 +483,7 @@ TEST(String, Increasing) { ASSERT_LT(EncodeStringIncreasing(STATIC_STR("\x01")), EncodeStringIncreasing(STATIC_STR("a"))); - ASSERT_EQ(EncodeStringIncreasing(STATIC_STR("a")), + EXPECT_EQ(EncodeStringIncreasing(STATIC_STR("a")), EncodeStringIncreasing(STATIC_STR("a"))); ASSERT_LT(EncodeStringIncreasing(STATIC_STR("a")), @@ -526,3 +502,7 @@ TEST(String, Increasing) { OrderedCode::WriteInfinity(&infinity); ASSERT_LT(EncodeStringIncreasing(std::string(1 << 20, '\xff')), infinity); } + +} // namespace util +} // namespace firestore +} // namespace firebase diff --git a/Firestore/core/test/firebase/firestore/util/secure_random_test.cc b/Firestore/core/test/firebase/firestore/util/secure_random_test.cc index ee2ae00..0b7a51b 100644 --- a/Firestore/core/test/firebase/firestore/util/secure_random_test.cc +++ b/Firestore/core/test/firebase/firestore/util/secure_random_test.cc @@ -30,3 +30,28 @@ TEST(SecureRandomTest, ResultsAreBounded) { EXPECT_LE(value, rng.max()); } } + +TEST(SecureRandomTest, Uniform) { + SecureRandom rng; + int count[10] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; + + for (int i = 0; i < 1000; i++) { + count[rng.Uniform(10)]++; + } + for (int i = 0; i < 10; i++) { + // Practically, each count should be close to 100. + EXPECT_LT(50, count[i]) << count[i]; + } +} + +TEST(SecureRandomTest, OneIn) { + SecureRandom rng; + int count = 0; + + for (int i = 0; i < 1000; i++) { + if (rng.OneIn(10)) count++; + } + // Practically, count should be close to 100. + EXPECT_LT(50, count) << count; + EXPECT_GT(150, count) << count; +} |