diff --git a/build_scripts/desktop/package.sh b/build_scripts/desktop/package.sh index 5a0fe327ac..31137d0fb1 100755 --- a/build_scripts/desktop/package.sh +++ b/build_scripts/desktop/package.sh @@ -193,6 +193,7 @@ readonly deps_hidden_firebase_app=" */boringssl-build/crypto/${subdir}${prefix}crypto.${ext} */boringssl-build/ssl/${subdir}${prefix}ssl.${ext} */firestore-build/*/leveldb-build*/${prefix}*.${ext} +*/firestore-build/*/snappy-build*/${prefix}*.${ext} */firestore-build/*/nanopb-build*/${prefix}*.${ext} " readonly deps_hidden_firebase_database=" @@ -227,7 +228,7 @@ readonly -a rename_namespaces=(flatbuffers flexbuffers reflection ZLib bssl uWS grpc_ssl_server_credentials grpc_tls_credential_reload_config grpc_tls_server_authorization_check_config GrpcUdpListener leveldb leveldb_filterpolicy_create_bloom leveldb_writebatch_iterate strings - TlsCredentials TlsServerCredentials tsi) + TlsCredentials TlsServerCredentials tsi snappy) # String to prepend to all hidden symbols. readonly rename_string=f_b_ diff --git a/cmake/external/firestore.cmake b/cmake/external/firestore.cmake index 8eea13f46c..d94c6681e3 100644 --- a/cmake/external/firestore.cmake +++ b/cmake/external/firestore.cmake @@ -32,6 +32,7 @@ function(GetReleasedDep version) BUILD_COMMAND "" INSTALL_COMMAND "" TEST_COMMAND "" + PATCH_COMMAND patch -Np1 -i ${CMAKE_CURRENT_LIST_DIR}/firestore_snappy.patch.txt HTTP_HEADER "${EXTERNAL_PROJECT_HTTP_HEADER}" ) endfunction() @@ -52,6 +53,7 @@ function(GetTag t) BUILD_COMMAND "" INSTALL_COMMAND "" TEST_COMMAND "" + PATCH_COMMAND patch -Np1 -i ${CMAKE_CURRENT_LIST_DIR}/firestore_snappy.patch.txt HTTP_HEADER "${EXTERNAL_PROJECT_HTTP_HEADER}" ) endfunction() diff --git a/cmake/external/firestore_snappy.patch.txt b/cmake/external/firestore_snappy.patch.txt new file mode 100644 index 0000000000..2261974b92 --- /dev/null +++ b/cmake/external/firestore_snappy.patch.txt @@ -0,0 +1,600 @@ +diff --git a/CMakeLists.txt b/CMakeLists.txt +index 29458bf13..7be37691d 100644 +--- a/CMakeLists.txt ++++ b/CMakeLists.txt +@@ -227,6 +227,12 @@ if(NOT ZLIB_FOUND) + endif() + + ++# Snappy ++set(SNAPPY_BUILD_TESTS OFF CACHE BOOL "Firestore disabled") ++set(SNAPPY_BUILD_BENCHMARKS OFF CACHE BOOL "Firestore disabled") ++add_external_subdirectory(snappy) ++firebase_ios_add_alias(Snappy::Snappy snappy) ++ + # LevelDB + set(LEVELDB_BUILD_TESTS OFF CACHE BOOL "Firestore disabled") + set(LEVELDB_BUILD_BENCHMARKS OFF CACHE BOOL "Firestore disabled") +diff --git a/cmake/external/CMakeLists.txt b/cmake/external/CMakeLists.txt +index 2179633a8..c1de37b6d 100644 +--- a/cmake/external/CMakeLists.txt ++++ b/cmake/external/CMakeLists.txt +@@ -30,6 +30,7 @@ include(c-ares) + include(googletest) + include(GoogleUtilities) + include(grpc) ++include(snappy) + include(leveldb) + include(libfuzzer) + include(nanopb) +diff --git a/cmake/external/leveldb.cmake b/cmake/external/leveldb.cmake +index b71a77535..2556d7041 100644 +--- a/cmake/external/leveldb.cmake ++++ b/cmake/external/leveldb.cmake +@@ -13,20 +13,27 @@ + # limitations under the License. + + include(ExternalProject) ++include(FindPythonInterp) + + if(TARGET leveldb) + return() + endif() + +-set(version 1.22) ++set(version 1.23) ++ ++ExternalProject_Get_property(snappy SOURCE_DIR) ++set(snappy_source_dir "${SOURCE_DIR}") ++ExternalProject_Get_property(snappy BINARY_DIR) ++set(snappy_binary_dir "${BINARY_DIR}") + + ExternalProject_Add( + leveldb + ++ DEPENDS snappy ++ + DOWNLOAD_DIR ${FIREBASE_DOWNLOAD_DIR} + DOWNLOAD_NAME leveldb-${version}.tar.gz + URL https://github.com/google/leveldb/archive/${version}.tar.gz +- URL_HASH SHA256=55423cac9e3306f4a9502c738a001e4a339d1a38ffbee7572d4a07d5d63949b2 + + PREFIX ${PROJECT_BINARY_DIR} + +@@ -34,6 +41,7 @@ ExternalProject_Add( + BUILD_COMMAND "" + INSTALL_COMMAND "" + TEST_COMMAND "" ++ PATCH_COMMAND ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_LIST_DIR}/leveldb_patch.py --snappy-source-dir ${snappy_source_dir} --snappy-binary-dir ${snappy_binary_dir} + + HTTP_HEADER "${EXTERNAL_PROJECT_HTTP_HEADER}" + ) +diff --git a/cmake/external/leveldb_patch.py b/cmake/external/leveldb_patch.py +new file mode 100644 +index 000000000..51a62d54a +--- /dev/null ++++ b/cmake/external/leveldb_patch.py +@@ -0,0 +1,144 @@ ++# Copyright 2022 Google LLC ++# ++# Licensed under the Apache License, Version 2.0 (the "License"); ++# you may not use this file except in compliance with the License. ++# You may obtain a copy of the License at ++# ++# http://www.apache.org/licenses/LICENSE-2.0 ++# ++# Unless required by applicable law or agreed to in writing, software ++# distributed under the License is distributed on an "AS IS" BASIS, ++# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. ++# See the License for the specific language governing permissions and ++# limitations under the License. ++ ++""" ++Modify the CMakeLists.txt from LevelDb to staticly link Snappy compression ++support. ++""" ++ ++import argparse ++import dataclasses ++import os ++import pathlib ++from typing import Iterable, Sequence ++ ++ ++def main() -> None: ++ arg_parser = argparse.ArgumentParser() ++ arg_parser.add_argument("--snappy-source-dir", required=True) ++ arg_parser.add_argument("--snappy-binary-dir", required=True) ++ parsed_args = arg_parser.parse_args() ++ del arg_parser ++ snappy_source_dir = pathlib.Path(parsed_args.snappy_source_dir) ++ snappy_binary_dir = pathlib.Path(parsed_args.snappy_binary_dir) ++ del parsed_args ++ ++ cmakelists_txt_file = pathlib.Path("CMakeLists.txt") ++ with cmakelists_txt_file.open("rt", encoding="utf8") as f: ++ lines = tuple(f) ++ ++ patcher = CMakeListsPatcher( ++ lines, ++ os.path.abspath(__file__), ++ snappy_source_dir, ++ snappy_binary_dir, ++ ) ++ ++ patched_lines = tuple(patcher.patch()) ++ ++ with cmakelists_txt_file.open("wt", encoding="utf8") as f: ++ f.writelines(patched_lines) ++ ++ ++@dataclasses.dataclass(frozen=True) ++class LineComponents: ++ full: str ++ indent: str ++ line: str ++ eol: str ++ ++ ++class CMakeListsPatcher: ++ ++ SNAPPY_DETECT_LINE = \ ++ """check_library_exists(snappy snappy_compress "" HAVE_SNAPPY)""" ++ SNAPPY_INCLUDE_LINE = \ ++ "target_include_directories(leveldb" ++ SNAPPY_LINK_LINE = \ ++ "target_link_libraries(leveldb snappy)" ++ ++ def __init__( ++ self, ++ lines: Sequence[str], ++ script_name: str, ++ snappy_source_dir: pathlib.Path, ++ snappy_binary_dir: pathlib.Path) -> None: ++ self.i = 0 ++ self.lines = lines ++ self.script_name = script_name ++ self.snappy_source_dir_str = snappy_source_dir.as_posix() ++ self.snappy_binary_dir_str = snappy_binary_dir.as_posix() ++ ++ def patch(self) -> Iterable[str]: ++ while self.i < len(self.lines): ++ full_line = self.lines[self.i] ++ line = self._split_line(full_line) ++ self.i += 1 ++ ++ if line.line == self.SNAPPY_DETECT_LINE: ++ yield from self._on_snappy_detect_line(line) ++ elif line.line == self.SNAPPY_INCLUDE_LINE: ++ yield full_line ++ yield from self._on_leveldb_include_start() ++ elif line.line == self.SNAPPY_LINK_LINE: ++ yield from self._on_leveldb_snappy_link_line(line) ++ else: ++ yield full_line ++ ++ def _begin_mod_line(self, mod_name: str) -> str: ++ return f"# BEGIN: {mod_name} modification by {self.script_name}" ++ ++ def _end_mod_line(self, mod_name: str) -> str: ++ return f"# END: {mod_name} modification by {self.script_name}" ++ ++ def _on_snappy_detect_line(self, line: LineComponents) -> Iterable[str]: ++ yield self._begin_mod_line("snappy_detect_line") + line.eol ++ yield line.indent + "# " + line.line + line.eol ++ yield line.indent + """set(HAVE_SNAPPY ON CACHE BOOL "")""" + line.eol ++ yield self._end_mod_line("snappy_detect_line") + line.eol ++ ++ def _on_leveldb_include_start(self) -> Iterable[str]: ++ line1 = self._split_line(self.lines[self.i]) ++ line2 = self._split_line(self.lines[self.i + 1]) ++ begin_mod_line = self._begin_mod_line("leveldb_include_start") ++ ++ if line1.line == begin_mod_line: ++ return ++ ++ yield begin_mod_line + line1.eol ++ yield line1.indent + "PRIVATE" + line1.eol ++ yield line2.indent + self.snappy_source_dir_str + line2.eol ++ yield line2.indent + self.snappy_binary_dir_str + line2.eol ++ yield self._end_mod_line("leveldb_include_start") + line1.eol ++ ++ def _on_leveldb_snappy_link_line(self, line: LineComponents) -> Iterable[str]: ++ yield self._begin_mod_line("leveldb_snappy_link_line") + line.eol ++ yield line.indent + "# " + line.line + line.eol ++ yield line.indent + f"target_link_libraries(leveldb Snappy::Snappy)" + line.eol ++ yield self._end_mod_line("leveldb_snappy_link_line") + line.eol ++ ++ def _split_line(self, line: str) -> LineComponents: ++ line_rstripped = line.rstrip() ++ eol = line[len(line_rstripped):] ++ line_stripped = line_rstripped.strip() ++ indent = line_rstripped[:len(line_rstripped) - len(line_stripped)] ++ return LineComponents(full=line, indent=indent, line=line_stripped, eol=eol) ++ ++ ++class LeveDbPatchException(Exception): ++ pass ++ ++ ++if __name__ == "__main__": ++ main() +diff --git a/cmake/external/leveldb_patch_test.py b/cmake/external/leveldb_patch_test.py +new file mode 100644 +index 000000000..b1d62526b +--- /dev/null ++++ b/cmake/external/leveldb_patch_test.py +@@ -0,0 +1,328 @@ ++# Copyright 2022 Google LLC ++# ++# Licensed under the Apache License, Version 2.0 (the "License"); ++# you may not use this file except in compliance with the License. ++# You may obtain a copy of the License at ++# ++# http://www.apache.org/licenses/LICENSE-2.0 ++# ++# Unless required by applicable law or agreed to in writing, software ++# distributed under the License is distributed on an "AS IS" BASIS, ++# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. ++# See the License for the specific language governing permissions and ++# limitations under the License. ++ ++import leveldb_patch ++import pathlib ++import unittest ++ ++ ++class CMakeListsPatcherTest(unittest.TestCase): ++ ++ def setUp(self): ++ super().setUp() ++ self.sample_snappy_source_dir = pathlib.Path("a/b/snappy_source_dir") ++ self.sample_snappy_binary_dir = pathlib.Path("a/b/snappy_binary_dir") ++ ++ def test_snappy_detect_line_is_commented_and_replaced(self): ++ lines = ( ++ """check_library_exists(snappy snappy_compress "" HAVE_SNAPPY)""", ++ ) ++ patcher = leveldb_patch.CMakeListsPatcher( ++ lines, ++ "MyCoolScript", ++ self.sample_snappy_source_dir, ++ self.sample_snappy_binary_dir, ++ ) ++ ++ patched_lines = tuple(patcher.patch()) ++ ++ self.assertSequenceEqual(patched_lines, [ ++ "# BEGIN: snappy_detect_line modification by MyCoolScript", ++ """# check_library_exists(snappy snappy_compress "" HAVE_SNAPPY)""", ++ """set(HAVE_SNAPPY ON CACHE BOOL "")""", ++ "# END: snappy_detect_line modification by MyCoolScript", ++ ]) ++ ++ def test_snappy_detect_line_has_indent_and_eol_preserved(self): ++ lines = ( ++ """ check_library_exists(snappy snappy_compress "" HAVE_SNAPPY) \n""", ++ ) ++ patcher = leveldb_patch.CMakeListsPatcher( ++ lines, ++ "MyCoolScript", ++ self.sample_snappy_source_dir, ++ self.sample_snappy_binary_dir, ++ ) ++ ++ patched_lines = tuple(patcher.patch()) ++ ++ self.assertSequenceEqual(patched_lines, [ ++ "# BEGIN: snappy_detect_line modification by MyCoolScript \n", ++ """ # check_library_exists(snappy snappy_compress "" HAVE_SNAPPY) \n""", ++ """ set(HAVE_SNAPPY ON CACHE BOOL "") \n""", ++ "# END: snappy_detect_line modification by MyCoolScript \n", ++ ]) ++ ++ def test_snappy_detect_line_does_not_affect_surrounding_lines(self): ++ lines = ( ++ "aaa", ++ "bbb", ++ """check_library_exists(snappy snappy_compress "" HAVE_SNAPPY)""", ++ "ccc", ++ "ddd", ++ ) ++ patcher = leveldb_patch.CMakeListsPatcher( ++ lines, ++ "MyCoolScript", ++ self.sample_snappy_source_dir, ++ self.sample_snappy_binary_dir, ++ ) ++ ++ patched_lines = tuple(patcher.patch()) ++ ++ self.assertSequenceEqual(patched_lines, [ ++ "aaa", ++ "bbb", ++ "# BEGIN: snappy_detect_line modification by MyCoolScript", ++ """# check_library_exists(snappy snappy_compress "" HAVE_SNAPPY)""", ++ """set(HAVE_SNAPPY ON CACHE BOOL "")""", ++ "# END: snappy_detect_line modification by MyCoolScript", ++ "ccc", ++ "ddd", ++ ]) ++ ++ def test_snappy_include_is_amended(self): ++ lines = ( ++ "target_include_directories(leveldb", ++ "PUBLIC", ++ "path1", ++ "path2", ++ ")", ++ ) ++ patcher = leveldb_patch.CMakeListsPatcher( ++ lines, ++ script_name="MyCoolSript", ++ snappy_source_dir=pathlib.Path("a/b"), ++ snappy_binary_dir=pathlib.Path("c/d"), ++ ) ++ ++ patched_lines = tuple(patcher.patch()) ++ ++ self.assertSequenceEqual(patched_lines, [ ++ "target_include_directories(leveldb", ++ "# BEGIN: leveldb_include_start modification by MyCoolSript", ++ "PRIVATE", ++ "a/b", ++ "c/d", ++ "# END: leveldb_include_start modification by MyCoolSript", ++ "PUBLIC", ++ "path1", ++ "path2", ++ ")", ++ ]) ++ ++ def test_snappy_include_lines_adopt_indenting_and_eol_convention(self): ++ lines = ( ++ "target_include_directories(leveldb\n", ++ " PUBLIC \n", ++ " path1 \n", ++ " path2 \n", ++ ")\n", ++ ) ++ patcher = leveldb_patch.CMakeListsPatcher( ++ lines, ++ script_name="MyCoolSript", ++ snappy_source_dir=pathlib.Path("a/b"), ++ snappy_binary_dir=pathlib.Path("c/d"), ++ ) ++ ++ patched_lines = tuple(patcher.patch()) ++ ++ self.assertSequenceEqual(patched_lines, [ ++ "target_include_directories(leveldb\n", ++ "# BEGIN: leveldb_include_start modification by MyCoolSript \n", ++ " PRIVATE \n", ++ " a/b \n", ++ " c/d \n", ++ "# END: leveldb_include_start modification by MyCoolSript \n", ++ " PUBLIC \n", ++ " path1 \n", ++ " path2 \n", ++ ")\n", ++ ]) ++ ++ def test_snappy_include_line_does_not_affect_surrounding_lines(self): ++ lines = ( ++ "aaa", ++ "bbb", ++ "target_include_directories(leveldb", ++ "PUBLIC", ++ "path1", ++ "path2", ++ ")", ++ "ccc", ++ "ddd", ++ ) ++ patcher = leveldb_patch.CMakeListsPatcher( ++ lines, ++ script_name="MyCoolSript", ++ snappy_source_dir=pathlib.Path("a/b"), ++ snappy_binary_dir=pathlib.Path("c/d"), ++ ) ++ ++ patched_lines = tuple(patcher.patch()) ++ ++ self.assertSequenceEqual(patched_lines, [ ++ "aaa", ++ "bbb", ++ "target_include_directories(leveldb", ++ "# BEGIN: leveldb_include_start modification by MyCoolSript", ++ "PRIVATE", ++ "a/b", ++ "c/d", ++ "# END: leveldb_include_start modification by MyCoolSript", ++ "PUBLIC", ++ "path1", ++ "path2", ++ ")", ++ "ccc", ++ "ddd", ++ ]) ++ ++ def test_leveldb_snappy_link_line_is_commented_and_replaced(self): ++ lines = ( ++ "target_link_libraries(leveldb snappy)", ++ ) ++ patcher = leveldb_patch.CMakeListsPatcher( ++ lines, ++ script_name="MyCoolSript", ++ snappy_source_dir=pathlib.Path("a/b"), ++ snappy_binary_dir=pathlib.Path("c/d"), ++ ) ++ ++ patched_lines = tuple(patcher.patch()) ++ ++ self.assertSequenceEqual(patched_lines, [ ++ "# BEGIN: leveldb_snappy_link_line modification by MyCoolSript", ++ "# target_link_libraries(leveldb snappy)", ++ "target_link_libraries(leveldb Snappy::Snappy)", ++ "# END: leveldb_snappy_link_line modification by MyCoolSript", ++ ]) ++ ++ def test_leveldb_snappy_link_line_has_indent_and_eol_preserved(self): ++ lines = ( ++ " target_link_libraries(leveldb snappy) \n", ++ ) ++ patcher = leveldb_patch.CMakeListsPatcher( ++ lines, ++ script_name="MyCoolSript", ++ snappy_source_dir=pathlib.Path("a/b"), ++ snappy_binary_dir=pathlib.Path("c/d"), ++ ) ++ ++ patched_lines = tuple(patcher.patch()) ++ ++ self.assertSequenceEqual(patched_lines, [ ++ "# BEGIN: leveldb_snappy_link_line modification by MyCoolSript \n", ++ " # target_link_libraries(leveldb snappy) \n", ++ " target_link_libraries(leveldb Snappy::Snappy) \n", ++ "# END: leveldb_snappy_link_line modification by MyCoolSript \n", ++ ]) ++ ++ def test_leveldb_snappy_link_line_does_not_affect_surrounding_lines(self): ++ lines = ( ++ "aaa", ++ "bbb", ++ "target_link_libraries(leveldb snappy)", ++ "ccc", ++ "ddd", ++ ) ++ patcher = leveldb_patch.CMakeListsPatcher( ++ lines, ++ script_name="MyCoolSript", ++ snappy_source_dir=pathlib.Path("a/b"), ++ snappy_binary_dir=pathlib.Path("c/d"), ++ ) ++ ++ patched_lines = tuple(patcher.patch()) ++ ++ self.assertSequenceEqual(patched_lines, [ ++ "aaa", ++ "bbb", ++ "# BEGIN: leveldb_snappy_link_line modification by MyCoolSript", ++ "# target_link_libraries(leveldb snappy)", ++ "target_link_libraries(leveldb Snappy::Snappy)", ++ "# END: leveldb_snappy_link_line modification by MyCoolSript", ++ "ccc", ++ "ddd", ++ ]) ++ ++ def test_all_patches_combined(self): ++ lines = ( ++ """check_library_exists(snappy snappy_compress "" HAVE_SNAPPY)""", ++ "target_include_directories(leveldb", ++ "PUBLIC", ++ "path1", ++ ")", ++ "target_link_libraries(leveldb snappy)", ++ ) ++ ++ patcher = leveldb_patch.CMakeListsPatcher( ++ lines, ++ script_name="MyCoolSript", ++ snappy_source_dir=pathlib.Path("a/b"), ++ snappy_binary_dir=pathlib.Path("c/d"), ++ ) ++ patched_lines = tuple(patcher.patch()) ++ ++ self.assertSequenceEqual(patched_lines, [ ++ "# BEGIN: snappy_detect_line modification by MyCoolSript", ++ """# check_library_exists(snappy snappy_compress "" HAVE_SNAPPY)""", ++ """set(HAVE_SNAPPY ON CACHE BOOL "")""", ++ "# END: snappy_detect_line modification by MyCoolSript", ++ "target_include_directories(leveldb", ++ "# BEGIN: leveldb_include_start modification by MyCoolSript", ++ "PRIVATE", ++ "a/b", ++ "c/d", ++ "# END: leveldb_include_start modification by MyCoolSript", ++ "PUBLIC", ++ "path1", ++ ")", ++ "# BEGIN: leveldb_snappy_link_line modification by MyCoolSript", ++ "# target_link_libraries(leveldb snappy)", ++ "target_link_libraries(leveldb Snappy::Snappy)", ++ "# END: leveldb_snappy_link_line modification by MyCoolSript", ++ ]) ++ ++ def test_idempotence(self): ++ lines = ( ++ """check_library_exists(snappy snappy_compress "" HAVE_SNAPPY)\n""", ++ "target_include_directories(leveldb", ++ "PUBLIC", ++ "path1", ++ ")", ++ "target_link_libraries(leveldb snappy)", ++ ) ++ ++ patcher1 = leveldb_patch.CMakeListsPatcher( ++ lines, ++ script_name="MyCoolSript", ++ snappy_source_dir=pathlib.Path("a/b"), ++ snappy_binary_dir=pathlib.Path("c/d"), ++ ) ++ patched_lines1 = tuple(patcher1.patch()) ++ patcher2 = leveldb_patch.CMakeListsPatcher( ++ patched_lines1, ++ script_name="MyCoolSript", ++ snappy_source_dir=pathlib.Path("a/b"), ++ snappy_binary_dir=pathlib.Path("c/d"), ++ ) ++ patched_lines2 = tuple(patcher2.patch()) ++ ++ self.assertSequenceEqual(patched_lines1, patched_lines2) ++ ++ ++if __name__ == "__main__": ++ unittest.main() +diff --git a/cmake/external/snappy.cmake b/cmake/external/snappy.cmake +new file mode 100644 +index 000000000..9f25c03d0 +--- /dev/null ++++ b/cmake/external/snappy.cmake +@@ -0,0 +1,39 @@ ++# Copyright 2022 Google LLC ++# ++# Licensed under the Apache License, Version 2.0 (the "License"); ++# you may not use this file except in compliance with the License. ++# You may obtain a copy of the License at ++# ++# http://www.apache.org/licenses/LICENSE-2.0 ++# ++# Unless required by applicable law or agreed to in writing, software ++# distributed under the License is distributed on an "AS IS" BASIS, ++# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. ++# See the License for the specific language governing permissions and ++# limitations under the License. ++ ++include(ExternalProject) ++ ++if(TARGET snappy) ++ return() ++endif() ++ ++set(version 1.1.9) ++ ++ExternalProject_Add( ++ snappy ++ ++ DOWNLOAD_DIR ${FIREBASE_DOWNLOAD_DIR} ++ DOWNLOAD_NAME snappy-${version}.tar.gz ++ URL https://github.com/google/snappy/archive/refs/tags/${version}.tar.gz ++ URL_HASH SHA256=75c1fbb3d618dd3a0483bff0e26d0a92b495bbe5059c8b4f1c962b478b6e06e7 ++ ++ PREFIX ${PROJECT_BINARY_DIR} ++ ++ CONFIGURE_COMMAND "" ++ BUILD_COMMAND "" ++ INSTALL_COMMAND "" ++ TEST_COMMAND "" ++ ++ HTTP_HEADER "${EXTERNAL_PROJECT_HTTP_HEADER}" ++) diff --git a/cmake/external_rules.cmake b/cmake/external_rules.cmake index e1da819709..f431d15289 100644 --- a/cmake/external_rules.cmake +++ b/cmake/external_rules.cmake @@ -134,11 +134,6 @@ function(download_external_sources) "\n#include \n") endif() endif() - if (FIREBASE_INCLUDE_FIRESTORE) - # Tweak Firestore's included version of leveldb to match our own. - file(INSTALL "${PROJECT_SOURCE_DIR}/cmake/external/leveldb.cmake" - DESTINATION "${PROJECT_BINARY_DIR}/external/src/firestore/cmake/external") - endif() endif() endfunction() diff --git a/firestore/integration_test_internal/CMakeLists.txt b/firestore/integration_test_internal/CMakeLists.txt index dbcdb16b96..d9d7d20849 100644 --- a/firestore/integration_test_internal/CMakeLists.txt +++ b/firestore/integration_test_internal/CMakeLists.txt @@ -129,6 +129,7 @@ set(FIREBASE_INTEGRATION_TEST_DESKTOP_AND_IOS_TEST_SRCS src/array_transform_test.cc src/cleanup_test.cc src/collection_reference_test.cc + src/leveldb_snappy_test.cc src/transaction_extra_test.cc ) diff --git a/firestore/integration_test_internal/integration_test.xcodeproj/project.pbxproj b/firestore/integration_test_internal/integration_test.xcodeproj/project.pbxproj index ca69e5f5b3..f6d13725de 100644 --- a/firestore/integration_test_internal/integration_test.xcodeproj/project.pbxproj +++ b/firestore/integration_test_internal/integration_test.xcodeproj/project.pbxproj @@ -92,6 +92,8 @@ D6ED33BD2606CD890058CBF9 /* future_test_util.cc in Sources */ = {isa = PBXBuildFile; fileRef = D6ED33B92606CD890058CBF9 /* future_test_util.cc */; }; D6ED33BE2606CD890058CBF9 /* integration_test_util.cc in Sources */ = {isa = PBXBuildFile; fileRef = D6ED33BB2606CD890058CBF9 /* integration_test_util.cc */; }; D86FB1D3D4A592C451A29369 /* firebase_firestore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = B7F45B5446094E107E88721A /* firebase_firestore.framework */; }; + EDEEC7632800CD0000EFBAAF /* leveldb_snappy_test.cc in Sources */ = {isa = PBXBuildFile; fileRef = EDEEC7622800CD0000EFBAAF /* leveldb_snappy_test.cc */; }; + EDEEC7642800CD0000EFBAAF /* leveldb_snappy_test.cc in Sources */ = {isa = PBXBuildFile; fileRef = EDEEC7622800CD0000EFBAAF /* leveldb_snappy_test.cc */; }; /* End PBXBuildFile section */ /* Begin PBXFileReference section */ @@ -166,6 +168,7 @@ D6ED33BB2606CD890058CBF9 /* integration_test_util.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = integration_test_util.cc; path = src/util/integration_test_util.cc; sourceTree = ""; }; D6ED33BC2606CD890058CBF9 /* future_test_util.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = future_test_util.h; path = src/util/future_test_util.h; sourceTree = ""; }; EAFAF9474EC412ADCC65F2CC /* firebase_firestore.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = firebase_firestore.framework; path = Frameworks/firebase_firestore.framework; sourceTree = ""; }; + EDEEC7622800CD0000EFBAAF /* leveldb_snappy_test.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = leveldb_snappy_test.cc; path = src/leveldb_snappy_test.cc; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -258,6 +261,7 @@ 5292271D1C85FB5500C89379 /* src */ = { isa = PBXGroup; children = ( + EDEEC7622800CD0000EFBAAF /* leveldb_snappy_test.cc */, 12D513182684C8D100A83FAA /* bundle_builder.cc */, 12D513192684C8D100A83FAA /* bundle_builder.h */, 12D513132684C8C200A83FAA /* bundle_test.cc */, @@ -537,6 +541,7 @@ D6C179E922CB322900C2651A /* ios_app_framework.mm in Sources */, D6C179F022CB32A000C2651A /* app_framework.cc in Sources */, D6AAAD442606C22D0025C53B /* field_value_test.cc in Sources */, + EDEEC7632800CD0000EFBAAF /* leveldb_snappy_test.cc in Sources */, D6AAAD562606C22D0025C53B /* query_network_test.cc in Sources */, D6AAAD552606C22D0025C53B /* listener_registration_test.cc in Sources */, 12D5131A2684C8D100A83FAA /* bundle_builder.cc in Sources */, @@ -581,6 +586,7 @@ BC1D6842267B00EB005DC2DA /* field_value_test.cc in Sources */, BC1D684D267B00EB005DC2DA /* server_timestamp_test.cc in Sources */, 12D5131B2684C8D100A83FAA /* bundle_builder.cc in Sources */, + EDEEC7642800CD0000EFBAAF /* leveldb_snappy_test.cc in Sources */, BC1D6841267B00EB005DC2DA /* query_test.cc in Sources */, BC1D684F267B00EB005DC2DA /* document_reference_test.cc in Sources */, BC1D6846267B00EB005DC2DA /* collection_reference_test.cc in Sources */, diff --git a/firestore/integration_test_internal/src/leveldb_snappy_test.cc b/firestore/integration_test_internal/src/leveldb_snappy_test.cc new file mode 100644 index 0000000000..33f2247cd8 --- /dev/null +++ b/firestore/integration_test_internal/src/leveldb_snappy_test.cc @@ -0,0 +1,250 @@ +/* + * Copyright 2022 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// This test file does not compile on Android because Android uses the built-in +// sqlite database, not LevelDb. +#if defined(__ANDROID__) +#error "This test should not be included in Android." +#endif + +#include +#include +#include +#include +#include + +#include "Firestore/core/src/local/leveldb_util.h" +#include "Firestore/core/src/util/filesystem.h" +#include "Firestore/core/src/util/path.h" + +#include "firebase_test_framework.h" +#include "gtest/gtest.h" +#include "leveldb/db.h" + +// TODO(dconeybe) Reference this test in the iOS SDK instead of making a +// copy of it here in the C++ SDK. + +namespace { + +using ::firebase::firestore::local::ConvertStatus; +using ::firebase::firestore::util::Filesystem; +using ::firebase::firestore::util::Path; + +// Creates a LevelDb database that uses Snappy compression for at least one of +// its blocks. Attempting to iterate over this database using a LevelDb library +// that does not have Snappy compression compiled in will return a failed status +// with reason "corruption". +Path CreateLevelDbDatabaseThatUsesSnappyCompression(); + +// This test ensures that we don't accidentally regress having added in Snappy +// compression support (https://github.com/firebase/firebase-ios-sdk/pull/9596). +TEST(LevelDbSnappy, LevelDbHasSnappySupportCompiledIn) { + // Do not run this test on iOS because LevelDb in iOS does not support Snappy. + SKIP_TEST_ON_IOS; + + Path leveldb_path = CreateLevelDbDatabaseThatUsesSnappyCompression(); + if (HasFatalFailure()) return; + + leveldb::Options options; + options.create_if_missing = false; + + std::unique_ptr db; + { + leveldb::DB* db_ptr; + leveldb::Status status = + leveldb::DB::Open(options, leveldb_path.ToUtf8String(), &db_ptr); + ASSERT_TRUE(status.ok()); + db.reset(db_ptr); + } + + // One of the assertions below will fail when LevelDb attempts to read a block + // that is compressed with Snappy and Snappy compression support is not + // compiled in. + std::unique_ptr it( + db->NewIterator(leveldb::ReadOptions())); + for (it->SeekToFirst(); it->Valid(); it->Next()) { + ASSERT_TRUE(it->status().ok()) << ConvertStatus(it->status()); + } + ASSERT_TRUE(it->status().ok()) << ConvertStatus(it->status()); +} + +const std::array LevelDbSnappyFile_000005_ldb{ + 0x84, 0x03, 0x80, 0x00, 0x42, 0x00, 0x85, 0x71, 0x75, 0x65, 0x72, 0x79, + 0x5F, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x00, 0x01, 0x8B, 0x43, 0x6F, + 0x6C, 0x41, 0x2F, 0x44, 0x6F, 0x63, 0x41, 0x2F, 0x43, 0x6F, 0x6C, 0x42, + 0x01, 0x0A, 0x68, 0x42, 0x7C, 0x66, 0x3A, 0x7C, 0x6F, 0x62, 0x3A, 0x5F, + 0x5F, 0x6E, 0x61, 0x6D, 0x65, 0x5F, 0x5F, 0x61, 0x73, 0x63, 0x00, 0x01, + 0x8C, 0x82, 0x80, 0x01, 0x07, 0x00, 0x05, 0x01, 0x08, 0x01, 0x13, 0x50, + 0x11, 0x3E, 0x01, 0x16, 0x00, 0x0A, 0x05, 0x15, 0xF0, 0x3C, 0x00, 0x08, + 0x02, 0x20, 0x05, 0x32, 0x4A, 0x12, 0x48, 0x70, 0x72, 0x6F, 0x6A, 0x65, + 0x63, 0x74, 0x73, 0x2F, 0x54, 0x65, 0x73, 0x74, 0x54, 0x65, 0x72, 0x6D, + 0x69, 0x6E, 0x61, 0x74, 0x65, 0x2F, 0x64, 0x61, 0x74, 0x61, 0x62, 0x61, + 0x73, 0x65, 0x73, 0x2F, 0x28, 0x64, 0x65, 0x66, 0x61, 0x75, 0x6C, 0x74, + 0x29, 0x2F, 0x64, 0x6F, 0x63, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x73, 0x01, + 0x7B, 0x3E, 0x85, 0x00, 0x0C, 0x0D, 0x07, 0x50, 0x08, 0x15, 0x5A, 0x00, + 0x03, 0xFE, 0x5A, 0x00, 0x2E, 0x5A, 0x00, 0x38, 0x07, 0x12, 0x06, 0x5F, + 0x67, 0x6C, 0x6F, 0x62, 0x61, 0x6C, 0x00, 0x01, 0x80, 0x01, 0x0B, 0x11, + 0x65, 0x1C, 0x10, 0x05, 0x20, 0x01, 0x12, 0x07, 0x06, 0x09, 0x15, 0x10, + 0x00, 0x03, 0x01, 0x10, 0x04, 0x00, 0x01, 0x09, 0x10, 0x24, 0x01, 0x12, + 0x01, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6F, 0x6E, 0x01, 0x35, 0x00, 0x06, + 0x09, 0x15, 0x10, 0x37, 0x0C, 0x07, 0x01, 0x05, 0x09, 0x0B, 0x10, 0x36, + 0x0C, 0x07, 0x01, 0x04, 0x09, 0x0B, 0x10, 0x35, 0x0C, 0x07, 0x01, 0x03, + 0x09, 0x0B, 0x4C, 0x34, 0x0C, 0x07, 0x01, 0x02, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x33, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, + 0x2C, 0x6E, 0xE0, 0xF4, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x00, 0xC0, 0xF2, 0xA1, 0xB0, 0x00, 0x09, 0x03, 0x86, 0x01, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x87, 0x02, 0x00, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x00, 0x58, 0xC2, 0x94, 0x06, 0x8C, 0x02, 0x08, + 0x99, 0x02, 0x17, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x57, 0xFB, 0x80, 0x8B, 0x24, 0x75, 0x47, 0xDB, +}; +const std::array LevelDbSnappyFile_000017_ldb{ + 0x00, 0x14, 0x50, 0x85, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x00, 0x01, + 0x8C, 0x82, 0x80, 0x01, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, + 0x02, 0x20, 0x0A, 0x32, 0x4A, 0x12, 0x48, 0x70, 0x72, 0x6F, 0x6A, 0x65, + 0x63, 0x74, 0x73, 0x2F, 0x54, 0x65, 0x73, 0x74, 0x54, 0x65, 0x72, 0x6D, + 0x69, 0x6E, 0x61, 0x74, 0x65, 0x2F, 0x64, 0x61, 0x74, 0x61, 0x62, 0x61, + 0x73, 0x65, 0x73, 0x2F, 0x28, 0x64, 0x65, 0x66, 0x61, 0x75, 0x6C, 0x74, + 0x29, 0x2F, 0x64, 0x6F, 0x63, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x73, 0x2F, + 0x43, 0x6F, 0x6C, 0x41, 0x2F, 0x44, 0x6F, 0x63, 0x41, 0x2F, 0x43, 0x6F, + 0x6C, 0x42, 0x2F, 0x44, 0x6F, 0x63, 0x42, 0x07, 0x12, 0x06, 0x5F, 0x67, + 0x6C, 0x6F, 0x62, 0x61, 0x6C, 0x00, 0x01, 0x80, 0x01, 0x0D, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x08, 0x02, 0x10, 0x0A, 0x20, 0x01, 0x00, 0x00, + 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0xFE, 0xCD, 0xE0, 0x39, 0x00, + 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0xC0, 0xF2, 0xA1, 0xB0, + 0x00, 0x09, 0x03, 0x86, 0x01, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0x00, 0x8A, 0x01, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, + 0xE4, 0xA7, 0x7E, 0x74, 0x8F, 0x01, 0x08, 0x9C, 0x01, 0x17, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x57, 0xFB, 0x80, 0x8B, + 0x24, 0x75, 0x47, 0xDB, +}; +const std::array LevelDbSnappyFile_000085_ldb{}; +const std::array LevelDbSnappyFile_CURRENT{ + 0x4D, 0x41, 0x4E, 0x49, 0x46, 0x45, 0x53, 0x54, + 0x2D, 0x30, 0x30, 0x30, 0x30, 0x38, 0x34, 0x0A, +}; +const std::array LevelDbSnappyFile_LOG_old{ + 0x32, 0x30, 0x32, 0x32, 0x2F, 0x30, 0x34, 0x2F, 0x30, 0x34, 0x2D, 0x31, + 0x31, 0x3A, 0x33, 0x39, 0x3A, 0x34, 0x36, 0x2E, 0x32, 0x35, 0x37, 0x32, + 0x35, 0x31, 0x20, 0x30, 0x78, 0x37, 0x30, 0x30, 0x30, 0x30, 0x35, 0x33, + 0x31, 0x34, 0x30, 0x30, 0x30, 0x20, 0x52, 0x65, 0x63, 0x6F, 0x76, 0x65, + 0x72, 0x69, 0x6E, 0x67, 0x20, 0x6C, 0x6F, 0x67, 0x20, 0x23, 0x38, 0x31, + 0x0A, 0x32, 0x30, 0x32, 0x32, 0x2F, 0x30, 0x34, 0x2F, 0x30, 0x34, 0x2D, + 0x31, 0x31, 0x3A, 0x33, 0x39, 0x3A, 0x34, 0x36, 0x2E, 0x33, 0x30, 0x34, + 0x35, 0x35, 0x32, 0x20, 0x30, 0x78, 0x37, 0x30, 0x30, 0x30, 0x30, 0x35, + 0x33, 0x31, 0x34, 0x30, 0x30, 0x30, 0x20, 0x44, 0x65, 0x6C, 0x65, 0x74, + 0x65, 0x20, 0x74, 0x79, 0x70, 0x65, 0x3D, 0x33, 0x20, 0x23, 0x38, 0x30, + 0x0A, 0x32, 0x30, 0x32, 0x32, 0x2F, 0x30, 0x34, 0x2F, 0x30, 0x34, 0x2D, + 0x31, 0x31, 0x3A, 0x33, 0x39, 0x3A, 0x34, 0x36, 0x2E, 0x33, 0x30, 0x35, + 0x30, 0x36, 0x34, 0x20, 0x30, 0x78, 0x37, 0x30, 0x30, 0x30, 0x30, 0x35, + 0x33, 0x31, 0x34, 0x30, 0x30, 0x30, 0x20, 0x44, 0x65, 0x6C, 0x65, 0x74, + 0x65, 0x20, 0x74, 0x79, 0x70, 0x65, 0x3D, 0x30, 0x20, 0x23, 0x38, 0x31, + 0x0A, +}; +const std::array LevelDbSnappyFile_LOG{ + 0x32, 0x30, 0x32, 0x32, 0x2F, 0x30, 0x34, 0x2F, 0x30, 0x34, 0x2D, 0x31, + 0x31, 0x3A, 0x35, 0x36, 0x3A, 0x35, 0x36, 0x2E, 0x34, 0x39, 0x33, 0x31, + 0x34, 0x32, 0x20, 0x30, 0x78, 0x37, 0x30, 0x30, 0x30, 0x30, 0x61, 0x32, + 0x35, 0x34, 0x30, 0x30, 0x30, 0x20, 0x52, 0x65, 0x63, 0x6F, 0x76, 0x65, + 0x72, 0x69, 0x6E, 0x67, 0x20, 0x6C, 0x6F, 0x67, 0x20, 0x23, 0x38, 0x33, + 0x0A, 0x32, 0x30, 0x32, 0x32, 0x2F, 0x30, 0x34, 0x2F, 0x30, 0x34, 0x2D, + 0x31, 0x31, 0x3A, 0x35, 0x36, 0x3A, 0x35, 0x36, 0x2E, 0x35, 0x33, 0x34, + 0x37, 0x34, 0x35, 0x20, 0x30, 0x78, 0x37, 0x30, 0x30, 0x30, 0x30, 0x61, + 0x32, 0x35, 0x34, 0x30, 0x30, 0x30, 0x20, 0x44, 0x65, 0x6C, 0x65, 0x74, + 0x65, 0x20, 0x74, 0x79, 0x70, 0x65, 0x3D, 0x33, 0x20, 0x23, 0x38, 0x32, + 0x0A, 0x32, 0x30, 0x32, 0x32, 0x2F, 0x30, 0x34, 0x2F, 0x30, 0x34, 0x2D, + 0x31, 0x31, 0x3A, 0x35, 0x36, 0x3A, 0x35, 0x36, 0x2E, 0x35, 0x33, 0x35, + 0x32, 0x34, 0x32, 0x20, 0x30, 0x78, 0x37, 0x30, 0x30, 0x30, 0x30, 0x61, + 0x32, 0x35, 0x34, 0x30, 0x30, 0x30, 0x20, 0x44, 0x65, 0x6C, 0x65, 0x74, + 0x65, 0x20, 0x74, 0x79, 0x70, 0x65, 0x3D, 0x30, 0x20, 0x23, 0x38, 0x33, + 0x0A, +}; +const std::array LevelDbSnappyFile_MANIFEST_000084{ + 0x45, 0x63, 0x9F, 0xDD, 0xAC, 0x00, 0x01, 0x01, 0x1A, 0x6C, 0x65, 0x76, + 0x65, 0x6C, 0x64, 0x62, 0x2E, 0x42, 0x79, 0x74, 0x65, 0x77, 0x69, 0x73, + 0x65, 0x43, 0x6F, 0x6D, 0x70, 0x61, 0x72, 0x61, 0x74, 0x6F, 0x72, 0x07, + 0x00, 0x05, 0xE5, 0x02, 0x42, 0x85, 0x71, 0x75, 0x65, 0x72, 0x79, 0x5F, + 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x00, 0x01, 0x8B, 0x43, 0x6F, 0x6C, + 0x41, 0x2F, 0x44, 0x6F, 0x63, 0x41, 0x2F, 0x43, 0x6F, 0x6C, 0x42, 0x2F, + 0x44, 0x6F, 0x63, 0x42, 0x7C, 0x66, 0x3A, 0x7C, 0x6F, 0x62, 0x3A, 0x5F, + 0x5F, 0x6E, 0x61, 0x6D, 0x65, 0x5F, 0x5F, 0x61, 0x73, 0x63, 0x00, 0x01, + 0x8C, 0x82, 0x80, 0x01, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x13, + 0x85, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6F, 0x6E, 0x00, 0x01, 0x80, 0x01, + 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x11, 0xE8, 0x01, + 0x14, 0x85, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x00, 0x01, 0x8C, 0x82, + 0x80, 0x01, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x19, 0x85, 0x74, + 0x61, 0x72, 0x67, 0x65, 0x74, 0x5F, 0x67, 0x6C, 0x6F, 0x62, 0x61, 0x6C, + 0x00, 0x01, 0x80, 0x01, 0x0D, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xB1, + 0x03, 0xAC, 0xBA, 0x08, 0x00, 0x01, 0x02, 0x55, 0x09, 0x00, 0x03, 0x56, + 0x04, 0x0D, +}; + +template +void WriteFile(const Path& dir, + const std::string& file_name, + const T& data_array) { + Filesystem* fs = Filesystem::Default(); + { + auto status = fs->RecursivelyCreateDir(dir); + if (!status.ok()) { + FAIL() << "Creating directory failed: " << dir.ToUtf8String() << " (" + << status.error_message() << ")"; + } + } + + Path file = dir.AppendUtf8(file_name); + std::ofstream out_file(file.native_value(), std::ios::binary); + if (!out_file) { + FAIL() << "Unable to open file for writing: " << file.ToUtf8String(); + } + + out_file.write(reinterpret_cast(data_array.data()), + data_array.size()); + out_file.close(); + if (!out_file) { + FAIL() << "Writing to file failed: " << file.ToUtf8String(); + } +} + +Path LevelDbDir() { + Filesystem* fs = Filesystem::Default(); + Path dir = fs->TempDir().AppendUtf8("PersistenceTesting"); + + // Delete the directory first to ensure isolation between runs. + auto status = fs->RecursivelyRemove(dir); + EXPECT_TRUE(status.ok()) << "Failed to clean up leveldb in dir " + << dir.ToUtf8String() << ": " << status.ToString(); + + return dir; +} + +Path CreateLevelDbDatabaseThatUsesSnappyCompression() { + Path leveldb_dir = LevelDbDir(); + WriteFile(leveldb_dir, "000005.ldb", LevelDbSnappyFile_000005_ldb); + WriteFile(leveldb_dir, "000017.ldb", LevelDbSnappyFile_000017_ldb); + WriteFile(leveldb_dir, "000085.ldb", LevelDbSnappyFile_000085_ldb); + WriteFile(leveldb_dir, "CURRENT", LevelDbSnappyFile_CURRENT); + WriteFile(leveldb_dir, "LOG.old", LevelDbSnappyFile_LOG_old); + WriteFile(leveldb_dir, "LOG", LevelDbSnappyFile_LOG); + WriteFile(leveldb_dir, "MANIFEST-000084", LevelDbSnappyFile_MANIFEST_000084); + return leveldb_dir; +} + +} // namespace diff --git a/release_build_files/readme.md b/release_build_files/readme.md index 7e51e3b9a7..cfa360135b 100644 --- a/release_build_files/readme.md +++ b/release_build_files/readme.md @@ -571,6 +571,9 @@ code. - Changes - Firestore/Database (Desktop): Upgrade LevelDb dependency to 1.23 ([#886](https://github.com/firebase/firebase-cpp-sdk/pull/886)). + - Firestore/Database (Desktop): Enabled Snappy compression support + in LevelDb + ([#885](https://github.com/firebase/firebase-cpp-sdk/pull/885)). ### 8.10.0 - Changes