mirror of
https://github.com/vicliu624/trail-mate.git
synced 2026-11-11 14:47:39 +00:00
149 lines
6.7 KiB
C++
149 lines
6.7 KiB
C++
#include "hostlink/route_storage_lease.h"
|
|
#include "platform/esp/arduino_common/route_image_source_runtime.h"
|
|
#include "platform/ui/http_client_runtime.h"
|
|
#include "platform/ui/route_storage.h"
|
|
#include <cassert>
|
|
#include <memory>
|
|
#include <string>
|
|
#if defined(_WIN32)
|
|
extern "C" void mbedtls_platform_zeroize(void* pointer, size_t length)
|
|
{
|
|
auto* bytes = static_cast<volatile uint8_t*>(pointer);
|
|
while (length--) *bytes++ = 0;
|
|
}
|
|
#endif
|
|
namespace image_http
|
|
{
|
|
inline bool ok = true, bad_stats = false, change_media = false;
|
|
inline unsigned calls = 0;
|
|
inline std::vector<uint8_t> body = {4, 5, 6, 7, 8};
|
|
} // namespace image_http
|
|
namespace platform::ui::device
|
|
{
|
|
bool sd_ready() { return image_fake::ready; }
|
|
} // namespace platform::ui::device
|
|
namespace platform::ui::http_client
|
|
{
|
|
bool download(const Request& request, WriteCallback callback, void* context, std::string& error, TransferStats* stats)
|
|
{
|
|
++image_http::calls;
|
|
assert(request.max_bytes <= track_sharing::kImageSourceByteLimit);
|
|
assert(request.buffer_size == 512 && request.tx_buffer_size == 512);
|
|
if (image_http::change_media) ++image_fake::media;
|
|
const bool written = callback(image_http::body.data(), 2, context) && callback(image_http::body.data() + 2, image_http::body.size() - 2, context);
|
|
stats->http_status = 200;
|
|
stats->bytes = uint32_t(image_http::body.size() + image_http::bad_stats);
|
|
if (!written || !image_http::ok)
|
|
{
|
|
error = "HTTP failed";
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
} // namespace platform::ui::http_client
|
|
namespace platform::ui::route_storage
|
|
{
|
|
constexpr size_t kRouteDownloadBufferSize = 512;
|
|
constexpr int kRouteDownloadTxBufferSize = 512;
|
|
constexpr size_t kRouteHttpInternalFreeTargetBytes = 18 * 1024, kRouteHttpInternalLargestTargetBytes = 8 * 1024;
|
|
bool route_image_url_supported(const std::string& url) { return url.substr(0, 8) == "https://"; }
|
|
bool ensure_parent_dir(const std::string&) { return true; }
|
|
inline void taskYIELD() {}
|
|
#include "image_download_actual.inc"
|
|
#include "image_query_public_actual.inc"
|
|
#include "image_query_reference_actual.inc"
|
|
} // namespace platform::ui::route_storage
|
|
int main()
|
|
{
|
|
using Work = platform::esp::route_images::RouteImageSourceWork;
|
|
static_assert(sizeof(Work) < 2048, "Image provenance workspace grew beyond its admission budget");
|
|
const std::string path = "/routes/.trailmate/kml-12345678/images/img-0001.jpg", url = "https://example.invalid/photo.jpg";
|
|
const auto reset = []()
|
|
{image_fake::reset();image_fake::psram=true;image_fake::allocation_fail=false;image_http::ok=true;image_http::bad_stats=false;image_http::change_media=false; };
|
|
reset();
|
|
auto download = [&](const std::string& target = std::string{})
|
|
{ return platform::ui::route_storage::download_route_image_with_progress(url, target.empty() ? path : target, 4096, nullptr, nullptr); };
|
|
const auto result = download();
|
|
assert(result.ok && result.bytes == 5 && image_fake::live == 0);
|
|
assert(image_fake::files.at(path) == image_http::body);
|
|
assert(image_fake::last_caps == (MALLOC_CAP_SPIRAM | MALLOC_CAP_8BIT));
|
|
uint8_t source_hash[32];
|
|
{
|
|
std::unique_ptr<Work> work(new (std::nothrow) Work);
|
|
assert(work && work->referenceHash(url, source_hash) && work->matchesExisting(path, source_hash));
|
|
source_hash[0] ^= 1;
|
|
assert(!work->matchesExisting(path, source_hash));
|
|
source_hash[0] ^= 1;
|
|
}
|
|
assert(image_fake::live == 0);
|
|
assert(platform::ui::route_storage::route_image_source_matches(path, source_hash));
|
|
assert(platform::ui::route_storage::route_image_source_matches_reference(path, url));
|
|
assert(!platform::ui::route_storage::route_image_source_matches_reference(path, url + "?different=1"));
|
|
image_fake::files[path] = {9, 9, 9};
|
|
{
|
|
std::unique_ptr<Work> work(new (std::nothrow) Work);
|
|
assert(!work->matchesExisting(path, source_hash));
|
|
}
|
|
reset();
|
|
image_fake::files[path] = {9, 9, 9};
|
|
{
|
|
std::unique_ptr<Work> work(new (std::nothrow) Work);
|
|
assert(!work->matchesExisting(path, source_hash));
|
|
}
|
|
for (const auto& invalid : {"/routes/.trailmate/../images/img-0001.jpg", "/routes/.trailmate/a/images/img-0000.jpg", "/routes/.trailmate/a/images/img-0065.jpg", "/routes/.trailmate/a/images/img-0001.jpg/../other", "/elsewhere/img-0001.jpg"})
|
|
{
|
|
reset();
|
|
const auto calls = image_http::calls;
|
|
assert(!download(invalid).ok && image_http::calls == calls && image_fake::files.empty());
|
|
}
|
|
reset();
|
|
image_fake::allocation_fail = true;
|
|
const auto calls = image_http::calls;
|
|
assert(!download().ok && image_http::calls == calls && image_fake::files.empty() && image_fake::last_caps == (MALLOC_CAP_SPIRAM | MALLOC_CAP_8BIT));
|
|
reset();
|
|
image_fake::psram = false;
|
|
assert(download().ok && image_fake::last_caps == (MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT));
|
|
reset();
|
|
image_http::bad_stats = true;
|
|
assert(!download().ok && !image_fake::files.count(path) && !image_fake::files.count(path + ".source"));
|
|
reset();
|
|
image_fake::flush_fail = true;
|
|
assert(!download().ok && !image_fake::files.count(path));
|
|
reset();
|
|
image_fake::write_fail = true;
|
|
assert(!download().ok && !image_fake::files.count(path));
|
|
reset();
|
|
image_http::ok = false;
|
|
assert(!download().ok && !image_fake::files.count(path));
|
|
reset();
|
|
image_http::change_media = true;
|
|
assert(!download().ok && !image_fake::files.count(path));
|
|
reset();
|
|
assert(hostlink::route_storage_lease::acquire());
|
|
const auto busy_calls = image_http::calls;
|
|
assert(!download().ok && image_http::calls == busy_calls && image_fake::files.empty());
|
|
hostlink::route_storage_lease::release();
|
|
reset();
|
|
assert(download().ok);
|
|
image_fake::files["/routes/.trailmate/kml-12345678/thumbs/thumb-0001.bmp"] = {9};
|
|
image_fake::files["/routes/.trailmate/kml-12345678/views/view-0001.bmp"] = {10};
|
|
image_http::body = {8, 7, 6, 5, 4};
|
|
assert(download().ok);
|
|
assert(!image_fake::files.count("/routes/.trailmate/kml-12345678/thumbs/thumb-0001.bmp") && !image_fake::files.count("/routes/.trailmate/kml-12345678/views/view-0001.bmp"));
|
|
reset();
|
|
image_fake::busy = true;
|
|
{
|
|
std::unique_ptr<Work> work(new (std::nothrow) Work);
|
|
assert(!work->matchesExisting(path, source_hash) && image_fake::removes == 0 && image_fake::renames == 0);
|
|
}
|
|
assert(image_fake::live == 0);
|
|
reset();
|
|
image_fake::files[path] = std::vector<uint8_t>(75, 1);
|
|
image_fake::open_fail = true;
|
|
{
|
|
platform::esp::route_images::SourceIo io;
|
|
assert(io.open(path.c_str(), decltype(io)::Mode::Read).status == decltype(io)::OpenStatus::Unavailable);
|
|
assert(io.open("/missing", decltype(io)::Mode::Read).status == decltype(io)::OpenStatus::Missing);
|
|
}
|
|
}
|