/* * Copyright (c) Meta Platforms, Inc. and affiliates. * * 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 #include "bcc_zip.h" #include "catch.hpp" #define LIB_ENTRY_NAME "libdebuginfo_test_lib.so" #define ENTRY_IN_SUBDIR_NAME "zip_subdir/file.txt" #define NOT_AN_ARCHIVE_PATH CMAKE_CURRENT_BINARY_DIR "/dummy_proc_map.txt" #define TEST_ARCHIVE_PATH CMAKE_CURRENT_BINARY_DIR "/archive.zip" namespace { void require_entry_name_is(const bcc_zip_entry& entry, const char* name) { REQUIRE(entry.name_length == strlen(name)); REQUIRE(memcmp(entry.name, name, strlen(name)) == 0); } bcc_zip_entry get_required_entry(bcc_zip_archive* archive, const char* asset_name) { bcc_zip_entry out; REQUIRE(bcc_zip_archive_find_entry(archive, asset_name, &out) == 0); require_entry_name_is(out, asset_name); return out; } const void* get_uncompressed_data(const bcc_zip_entry& entry) { REQUIRE(entry.compression == 0); REQUIRE(entry.data_offset > 0); REQUIRE(entry.data != nullptr); return entry.data; } } // namespace TEST_CASE("returns error for non-zip files", "[zip]") { bcc_zip_archive* archive = bcc_zip_archive_open(NOT_AN_ARCHIVE_PATH); REQUIRE(archive == nullptr); } TEST_CASE("finds entries in a zip archive by name", "[zip]") { bcc_zip_archive* archive = bcc_zip_archive_open(TEST_ARCHIVE_PATH); REQUIRE(archive != nullptr); bcc_zip_entry entry = get_required_entry(archive, LIB_ENTRY_NAME); REQUIRE(memcmp(get_uncompressed_data(entry), "\x7f" "ELF", 4) == 0); entry = get_required_entry(archive, ENTRY_IN_SUBDIR_NAME); REQUIRE(memcmp(get_uncompressed_data(entry), "This is a text file\n", 20) == 0); REQUIRE(bcc_zip_archive_find_entry(archive, "missing", &entry) == -1); bcc_zip_archive_close(archive); } TEST_CASE("finds entries in a zip archive by offset", "[zip]") { bcc_zip_archive* archive = bcc_zip_archive_open(TEST_ARCHIVE_PATH); REQUIRE(archive != nullptr); bcc_zip_entry entry; REQUIRE(bcc_zip_archive_find_entry_at_offset(archive, 100, &entry) == 0); require_entry_name_is(entry, LIB_ENTRY_NAME); REQUIRE(memcmp(get_uncompressed_data(entry), "\x7f" "ELF", 4) == 0); REQUIRE(bcc_zip_archive_find_entry_at_offset(archive, 100000, &entry) == -1); bcc_zip_archive_close(archive); } TEST_CASE("open zip archive and finds an entry", "[zip]") { bcc_zip_entry entry; bcc_zip_archive* archive = bcc_zip_archive_open_and_find( TEST_ARCHIVE_PATH "!/" LIB_ENTRY_NAME, &entry); REQUIRE(archive != nullptr); require_entry_name_is(entry, LIB_ENTRY_NAME); REQUIRE(memcmp(get_uncompressed_data(entry), "\x7f" "ELF", 4) == 0); bcc_zip_archive_close(archive); archive = bcc_zip_archive_open_and_find( TEST_ARCHIVE_PATH "!/" ENTRY_IN_SUBDIR_NAME, &entry); REQUIRE(archive != nullptr); require_entry_name_is(entry, ENTRY_IN_SUBDIR_NAME); REQUIRE(memcmp(get_uncompressed_data(entry), "This is a text file\n", 20) == 0); bcc_zip_archive_close(archive); archive = bcc_zip_archive_open_and_find(TEST_ARCHIVE_PATH "!/NOT_FOUND", &entry); REQUIRE(archive == nullptr); }