/* * This file is part of the Aaru Data Preservation Suite. * Copyright (c) 2019-2026 Natalia Portillo. * * Minimal ISO 9660 reader tests using a synthetic test ISO. */ #include #include #include #include #include #include "decls.h" #include "gtest/gtest.h" extern "C" { #include "../tool/ps3/iso9660_mini.h" #include "../tool/ps3/sfo.h" } /* In-memory ISO image for testing */ static uint8_t *iso_data = nullptr; static uint32_t iso_size = 0; static bool iso_loaded = false; static void load_iso() { if(iso_loaded) return; char path[PATH_MAX]; getcwd(path, PATH_MAX); char filename[PATH_MAX]; snprintf(filename, PATH_MAX, "%s/data/ps3_test.iso", path); FILE *f = fopen(filename, "rb"); if(f == nullptr) return; fseek(f, 0, SEEK_END); iso_size = (uint32_t)ftell(f); rewind(f); iso_data = (uint8_t *)malloc(iso_size); if(iso_data != nullptr) fread(iso_data, 1, iso_size, f); fclose(f); iso_loaded = true; } /* Sector read callback: reads from in-memory ISO */ static int32_t test_read_sector(void *user_data, uint64_t sector, uint8_t *buffer) { (void)user_data; uint64_t offset = sector * ISO9660_SECTOR_SIZE; if(offset + ISO9660_SECTOR_SIZE > iso_size) return -1; memcpy(buffer, iso_data + offset, ISO9660_SECTOR_SIZE); return 0; } class Iso9660Fixture : public ::testing::Test { protected: void SetUp() override { load_iso(); ASSERT_NE(nullptr, iso_data) << "Cannot load ps3_test.iso"; } }; /* Test: read PARAM.SFO from /PS3_GAME/PARAM.SFO */ TEST_F(Iso9660Fixture, ReadParamSfo) { uint8_t *data = nullptr; uint32_t length = 0; int32_t ret = iso9660_read_file(test_read_sector, nullptr, "/PS3_GAME/PARAM.SFO", &data, &length); ASSERT_EQ(0, ret); ASSERT_NE(nullptr, data); EXPECT_GT(length, 0u); /* The file should be a valid SFO */ SfoFile sfo; ret = ps3_parse_sfo(data, length, &sfo); EXPECT_EQ(0, ret); EXPECT_GT(sfo.entry_count, 0u); /* Verify a known field */ const char *title = ps3_sfo_get_string(&sfo, "TITLE"); EXPECT_NE(nullptr, title); if(title != nullptr) EXPECT_STREQ("Test Game Title", title); ps3_free_sfo(&sfo); free(data); } /* Test: path without leading slash */ TEST_F(Iso9660Fixture, ReadWithoutLeadingSlash) { uint8_t *data = nullptr; uint32_t length = 0; int32_t ret = iso9660_read_file(test_read_sector, nullptr, "PS3_GAME/PARAM.SFO", &data, &length); ASSERT_EQ(0, ret); ASSERT_NE(nullptr, data); EXPECT_GT(length, 0u); free(data); } /* Test: case insensitive path */ TEST_F(Iso9660Fixture, CaseInsensitive) { uint8_t *data = nullptr; uint32_t length = 0; int32_t ret = iso9660_read_file(test_read_sector, nullptr, "/ps3_game/param.sfo", &data, &length); ASSERT_EQ(0, ret); ASSERT_NE(nullptr, data); EXPECT_GT(length, 0u); free(data); } /* Test: nonexistent file returns error */ TEST_F(Iso9660Fixture, FileNotFound) { uint8_t *data = nullptr; uint32_t length = 0; int32_t ret = iso9660_read_file(test_read_sector, nullptr, "/NONEXISTENT/FILE.TXT", &data, &length); EXPECT_LT(ret, 0); EXPECT_EQ(nullptr, data); } /* Test: nonexistent directory returns error */ TEST_F(Iso9660Fixture, DirNotFound) { uint8_t *data = nullptr; uint32_t length = 0; int32_t ret = iso9660_read_file(test_read_sector, nullptr, "/PS3_GAME/NONEXISTENT.BIN", &data, &length); EXPECT_LT(ret, 0); } /* Test: NULL arguments */ TEST(Iso9660Errors, NullArgs) { uint8_t *data; uint32_t length; EXPECT_LT(iso9660_read_file(nullptr, nullptr, "/test", &data, &length), 0); EXPECT_LT(iso9660_read_file(test_read_sector, nullptr, nullptr, &data, &length), 0); EXPECT_LT(iso9660_read_file(test_read_sector, nullptr, "/test", nullptr, &length), 0); EXPECT_LT(iso9660_read_file(test_read_sector, nullptr, "/test", &data, nullptr), 0); } /* Test: sector read failure */ static int32_t fail_read_sector(void * /*user_data*/, uint64_t /*sector*/, uint8_t * /*buffer*/) { return -1; } TEST(Iso9660Errors, ReadFailure) { uint8_t *data = nullptr; uint32_t length = 0; int32_t ret = iso9660_read_file(fail_read_sector, nullptr, "/PS3_GAME/PARAM.SFO", &data, &length); EXPECT_LT(ret, 0); }