aboutsummaryrefslogtreecommitdiff
path: root/test/unit/test_network.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'test/unit/test_network.cpp')
-rw-r--r--test/unit/test_network.cpp386
1 files changed, 385 insertions, 1 deletions
diff --git a/test/unit/test_network.cpp b/test/unit/test_network.cpp
index 2ec38e41..4e66d8c5 100644
--- a/test/unit/test_network.cpp
+++ b/test/unit/test_network.cpp
@@ -38,6 +38,12 @@
#include <sqlite3.h>
#include <time.h>
+#ifdef _WIN32
+#include <windows.h>
+#else
+#include <unistd.h>
+#endif
+
#ifdef CURL_ENABLED
#include <curl/curl.h>
#endif
@@ -473,7 +479,30 @@ TEST(networking, custom) {
}
exchange.events.emplace_back(std::move(event));
}
-
+ {
+ std::unique_ptr<GetHeaderValueEvent> event(new GetHeaderValueEvent());
+ event->ctx = ctx;
+ event->key = "Content-Range";
+ event->value = "bytes=0-16383/10000000";
+ event->file_id = 2;
+ exchange.events.emplace_back(std::move(event));
+ }
+ {
+ std::unique_ptr<GetHeaderValueEvent> event(new GetHeaderValueEvent());
+ event->ctx = ctx;
+ event->key = "Last-Modified";
+ event->value = "some_date";
+ event->file_id = 2;
+ exchange.events.emplace_back(std::move(event));
+ }
+ {
+ std::unique_ptr<GetHeaderValueEvent> event(new GetHeaderValueEvent());
+ event->ctx = ctx;
+ event->key = "ETag";
+ event->value = "some_etag";
+ event->file_id = 2;
+ exchange.events.emplace_back(std::move(event));
+ }
{
double lon = 2 / 180. * M_PI;
double lat = 49 / 180. * M_PI;
@@ -500,6 +529,30 @@ TEST(networking, custom) {
}
exchange.events.emplace_back(std::move(event));
}
+ {
+ std::unique_ptr<GetHeaderValueEvent> event(new GetHeaderValueEvent());
+ event->ctx = ctx;
+ event->key = "Content-Range";
+ event->value = "bytes=0-16383/10000000";
+ event->file_id = 2;
+ exchange.events.emplace_back(std::move(event));
+ }
+ {
+ std::unique_ptr<GetHeaderValueEvent> event(new GetHeaderValueEvent());
+ event->ctx = ctx;
+ event->key = "Last-Modified";
+ event->value = "some_date";
+ event->file_id = 2;
+ exchange.events.emplace_back(std::move(event));
+ }
+ {
+ std::unique_ptr<GetHeaderValueEvent> event(new GetHeaderValueEvent());
+ event->ctx = ctx;
+ event->key = "ETag";
+ event->value = "some_etag";
+ event->file_id = 2;
+ exchange.events.emplace_back(std::move(event));
+ }
{
double lon = 2 / 180. * M_PI;
@@ -743,6 +796,30 @@ TEST(networking, simul_read_range_error) {
}
exchange.events.emplace_back(std::move(event));
}
+ {
+ std::unique_ptr<GetHeaderValueEvent> event(new GetHeaderValueEvent());
+ event->ctx = ctx;
+ event->key = "Content-Range";
+ event->value = "bytes=0-16383/10000000";
+ event->file_id = 2;
+ exchange.events.emplace_back(std::move(event));
+ }
+ {
+ std::unique_ptr<GetHeaderValueEvent> event(new GetHeaderValueEvent());
+ event->ctx = ctx;
+ event->key = "Last-Modified";
+ event->value = "some_date";
+ event->file_id = 2;
+ exchange.events.emplace_back(std::move(event));
+ }
+ {
+ std::unique_ptr<GetHeaderValueEvent> event(new GetHeaderValueEvent());
+ event->ctx = ctx;
+ event->key = "ETag";
+ event->value = "some_etag";
+ event->file_id = 2;
+ exchange.events.emplace_back(std::move(event));
+ }
{
double lon = 2 / 180. * M_PI;
@@ -793,6 +870,188 @@ TEST(networking, simul_read_range_error) {
// ---------------------------------------------------------------------------
+TEST(networking, simul_file_change_while_opened) {
+ auto ctx = proj_context_create();
+ proj_grid_cache_set_enable(ctx, false);
+ proj_context_set_enable_network(ctx, true);
+ ExchangeWithCallback exchange;
+ ASSERT_TRUE(proj_context_set_network_callbacks(ctx, open_cbk, close_cbk,
+ get_header_value_cbk,
+ read_range_cbk, &exchange));
+
+ {
+ std::unique_ptr<OpenEvent> event(new OpenEvent());
+ event->ctx = ctx;
+ event->url = "https://foo/file_change_while_opened.tif";
+ event->offset = 0;
+ event->size_to_read = 16384;
+ event->response.resize(16384);
+ event->file_id = 1;
+
+ const char *proj_source_data = getenv("PROJ_SOURCE_DATA");
+ ASSERT_TRUE(proj_source_data != nullptr);
+ std::string filename(proj_source_data);
+ filename += "/tests/egm96_15_uncompressed_truncated.tif";
+ FILE *f = fopen(filename.c_str(), "rb");
+ ASSERT_TRUE(f != nullptr);
+ ASSERT_EQ(fread(&event->response[0], 1, 956, f), 956U);
+ fclose(f);
+ exchange.events.emplace_back(std::move(event));
+ }
+ {
+ std::unique_ptr<GetHeaderValueEvent> event(new GetHeaderValueEvent());
+ event->ctx = ctx;
+ event->key = "Content-Range";
+ event->value = "bytes=0-16383/10000000";
+ event->file_id = 1;
+ exchange.events.emplace_back(std::move(event));
+ }
+ {
+ std::unique_ptr<GetHeaderValueEvent> event(new GetHeaderValueEvent());
+ event->ctx = ctx;
+ event->key = "Last-Modified";
+ event->value = "some_date";
+ event->file_id = 1;
+ exchange.events.emplace_back(std::move(event));
+ }
+ {
+ std::unique_ptr<GetHeaderValueEvent> event(new GetHeaderValueEvent());
+ event->ctx = ctx;
+ event->key = "ETag";
+ event->value = "some_etag";
+ event->file_id = 1;
+ exchange.events.emplace_back(std::move(event));
+ }
+ {
+ std::unique_ptr<CloseEvent> event(new CloseEvent());
+ event->ctx = ctx;
+ event->file_id = 1;
+ exchange.events.emplace_back(std::move(event));
+ }
+
+ auto P = proj_create(ctx, "+proj=vgridshift "
+ "+grids=https://foo/file_change_while_opened.tif "
+ "+multiplier=1");
+
+ ASSERT_NE(P, nullptr);
+ ASSERT_TRUE(exchange.allConsumedAndNoError());
+
+ {
+ std::unique_ptr<OpenEvent> event(new OpenEvent());
+ event->ctx = ctx;
+ event->url = "https://foo/file_change_while_opened.tif";
+ event->offset = 524288;
+ event->size_to_read = 278528;
+ event->response.resize(278528);
+ event->file_id = 2;
+ float f = 1.25;
+ for (size_t i = 0; i < 278528 / sizeof(float); i++) {
+ memcpy(&event->response[i * sizeof(float)], &f, sizeof(float));
+ }
+ exchange.events.emplace_back(std::move(event));
+ }
+ {
+ std::unique_ptr<GetHeaderValueEvent> event(new GetHeaderValueEvent());
+ event->ctx = ctx;
+ event->key = "Content-Range";
+ event->value = "bytes=0-16383/10000000";
+ event->file_id = 2;
+ exchange.events.emplace_back(std::move(event));
+ }
+ {
+ std::unique_ptr<GetHeaderValueEvent> event(new GetHeaderValueEvent());
+ event->ctx = ctx;
+ event->key = "Last-Modified";
+ event->value = "some_date CHANGED!!!!";
+ event->file_id = 2;
+ exchange.events.emplace_back(std::move(event));
+ }
+ {
+ std::unique_ptr<GetHeaderValueEvent> event(new GetHeaderValueEvent());
+ event->ctx = ctx;
+ event->key = "ETag";
+ event->value = "some_etag";
+ event->file_id = 2;
+ exchange.events.emplace_back(std::move(event));
+ }
+ {
+ std::unique_ptr<CloseEvent> event(new CloseEvent());
+ event->ctx = ctx;
+ event->file_id = 2;
+ exchange.events.emplace_back(std::move(event));
+ }
+ {
+ std::unique_ptr<OpenEvent> event(new OpenEvent());
+ event->ctx = ctx;
+ event->url = "https://foo/file_change_while_opened.tif";
+ event->offset = 0;
+ event->size_to_read = 16384;
+ event->response.resize(16384);
+ event->file_id = 3;
+
+ const char *proj_source_data = getenv("PROJ_SOURCE_DATA");
+ ASSERT_TRUE(proj_source_data != nullptr);
+ std::string filename(proj_source_data);
+ filename += "/tests/egm96_15_uncompressed_truncated.tif";
+ FILE *f = fopen(filename.c_str(), "rb");
+ ASSERT_TRUE(f != nullptr);
+ ASSERT_EQ(fread(&event->response[0], 1, 956, f), 956U);
+ fclose(f);
+ exchange.events.emplace_back(std::move(event));
+ }
+ {
+ std::unique_ptr<GetHeaderValueEvent> event(new GetHeaderValueEvent());
+ event->ctx = ctx;
+ event->key = "Content-Range";
+ event->value = "bytes=0-16383/10000000";
+ event->file_id = 3;
+ exchange.events.emplace_back(std::move(event));
+ }
+ {
+ std::unique_ptr<GetHeaderValueEvent> event(new GetHeaderValueEvent());
+ event->ctx = ctx;
+ event->key = "Last-Modified";
+ event->value = "some_date CHANGED!!!!";
+ event->file_id = 3;
+ exchange.events.emplace_back(std::move(event));
+ }
+ {
+ std::unique_ptr<GetHeaderValueEvent> event(new GetHeaderValueEvent());
+ event->ctx = ctx;
+ event->key = "ETag";
+ event->value = "some_etag";
+ event->file_id = 3;
+ exchange.events.emplace_back(std::move(event));
+ }
+
+ {
+ double lon = 2 / 180. * M_PI;
+ double lat = 49 / 180. * M_PI;
+ double z = 0;
+ ASSERT_EQ(proj_trans_generic(P, PJ_FWD, &lon, sizeof(double), 1, &lat,
+ sizeof(double), 1, &z, sizeof(double), 1,
+ nullptr, 0, 0),
+ 1U);
+ EXPECT_EQ(z, 1.25);
+ }
+
+ ASSERT_TRUE(exchange.allConsumedAndNoError());
+
+ {
+ std::unique_ptr<CloseEvent> event(new CloseEvent());
+ event->ctx = ctx;
+ event->file_id = 3;
+ exchange.events.emplace_back(std::move(event));
+ }
+ proj_destroy(P);
+
+ ASSERT_TRUE(exchange.allConsumedAndNoError());
+
+ proj_context_destroy(ctx);
+}
+
+// ---------------------------------------------------------------------------
+
#ifdef CURL_ENABLED
TEST(networking, curl_hgridshift) {
@@ -1305,6 +1564,131 @@ TEST(networking, cache_lock) {
proj_context_destroy(ctx);
}
+
+// ---------------------------------------------------------------------------
+
+TEST(networking, download_whole_files) {
+ if (!networkAccessOK) {
+ return;
+ }
+
+ proj_cleanup();
+ unlink("proj_test_tmp/cache.db");
+ unlink("proj_test_tmp/ntf_r93.tif");
+ rmdir("proj_test_tmp");
+
+ putenv(const_cast<char *>("PROJ_IGNORE_USER_WRITABLE_DIRECTORY="));
+ putenv(const_cast<char *>("PROJ_USER_WRITABLE_DIRECTORY=./proj_test_tmp"));
+ putenv(const_cast<char *>("PROJ_FULL_FILE_CHUNK_SIZE=30000"));
+ auto ctx = proj_context_create();
+ proj_context_set_enable_network(ctx, true);
+
+ ASSERT_TRUE(proj_is_download_needed(ctx, "ntf_r93.gsb", false));
+
+ ASSERT_TRUE(
+ proj_download_file(ctx, "ntf_r93.gsb", false, nullptr, nullptr));
+
+ FILE *f = fopen("proj_test_tmp/ntf_r93.tif", "rb");
+ ASSERT_NE(f, nullptr);
+ fseek(f, 0, SEEK_END);
+ ASSERT_EQ(ftell(f), 93581);
+ fclose(f);
+
+ ASSERT_FALSE(proj_is_download_needed(ctx, "ntf_r93.gsb", false));
+
+ {
+ sqlite3 *hDB = nullptr;
+ sqlite3_open_v2("proj_test_tmp/cache.db", &hDB, SQLITE_OPEN_READWRITE,
+ nullptr);
+ ASSERT_NE(hDB, nullptr);
+ // Force lastChecked to the Epoch so that data is expired.
+ sqlite3_stmt *hStmt = nullptr;
+ sqlite3_prepare_v2(
+ hDB, "UPDATE downloaded_file_properties SET lastChecked = 0", -1,
+ &hStmt, nullptr);
+ ASSERT_NE(hStmt, nullptr);
+ ASSERT_EQ(sqlite3_step(hStmt), SQLITE_DONE);
+ sqlite3_finalize(hStmt);
+ sqlite3_close(hDB);
+ }
+
+ // If we ignore TTL settings, then no network access will be done
+ ASSERT_FALSE(proj_is_download_needed(ctx, "ntf_r93.gsb", true));
+
+ {
+ sqlite3 *hDB = nullptr;
+ sqlite3_open_v2("proj_test_tmp/cache.db", &hDB, SQLITE_OPEN_READWRITE,
+ nullptr);
+ ASSERT_NE(hDB, nullptr);
+ // Check that the lastChecked timestamp is still 0
+ sqlite3_stmt *hStmt = nullptr;
+ sqlite3_prepare_v2(hDB,
+ "SELECT lastChecked FROM downloaded_file_properties",
+ -1, &hStmt, nullptr);
+ ASSERT_NE(hStmt, nullptr);
+ ASSERT_EQ(sqlite3_step(hStmt), SQLITE_ROW);
+ ASSERT_EQ(sqlite3_column_int64(hStmt, 0), 0);
+ sqlite3_finalize(hStmt);
+ sqlite3_close(hDB);
+ }
+
+ // Should recheck from the CDN, update last_checked and do nothing
+ ASSERT_FALSE(proj_is_download_needed(ctx, "ntf_r93.gsb", false));
+
+ {
+ sqlite3 *hDB = nullptr;
+ sqlite3_open_v2("proj_test_tmp/cache.db", &hDB, SQLITE_OPEN_READWRITE,
+ nullptr);
+ ASSERT_NE(hDB, nullptr);
+ sqlite3_stmt *hStmt = nullptr;
+ // Check that the lastChecked timestamp has been updated
+ sqlite3_prepare_v2(hDB,
+ "SELECT lastChecked FROM downloaded_file_properties",
+ -1, &hStmt, nullptr);
+ ASSERT_NE(hStmt, nullptr);
+ ASSERT_EQ(sqlite3_step(hStmt), SQLITE_ROW);
+ ASSERT_NE(sqlite3_column_int64(hStmt, 0), 0);
+ sqlite3_finalize(hStmt);
+ hStmt = nullptr;
+
+ // Now invalid lastModified. This should trigger a new download
+ sqlite3_prepare_v2(
+ hDB, "UPDATE downloaded_file_properties SET lastChecked = 0, "
+ "lastModified = 'foo'",
+ -1, &hStmt, nullptr);
+ ASSERT_NE(hStmt, nullptr);
+ ASSERT_EQ(sqlite3_step(hStmt), SQLITE_DONE);
+ sqlite3_finalize(hStmt);
+ sqlite3_close(hDB);
+ }
+
+ ASSERT_TRUE(proj_is_download_needed(ctx, "ntf_r93.gsb", false));
+
+ // Redo download with a progress callback this time.
+ unlink("proj_test_tmp/ntf_r93.tif");
+
+ const auto cbk = [](PJ_CONTEXT *l_ctx, double pct, void *user_data) -> int {
+ auto vect = static_cast<std::vector<std::pair<PJ_CONTEXT *, double>> *>(
+ user_data);
+ vect->push_back(std::pair<PJ_CONTEXT *, double>(l_ctx, pct));
+ return true;
+ };
+
+ std::vector<std::pair<PJ_CONTEXT *, double>> vectPct;
+ ASSERT_TRUE(proj_download_file(ctx, "ntf_r93.gsb", false, cbk, &vectPct));
+ ASSERT_EQ(vectPct.size(), 3U);
+ ASSERT_EQ(vectPct.back().first, ctx);
+ ASSERT_EQ(vectPct.back().second, 1.0);
+
+ proj_context_destroy(ctx);
+ putenv(const_cast<char *>("PROJ_IGNORE_USER_WRITABLE_DIRECTORY=YES"));
+ putenv(const_cast<char *>("PROJ_USER_WRITABLE_DIRECTORY="));
+ putenv(const_cast<char *>("PROJ_FULL_FILE_CHUNK_SIZE="));
+ unlink("proj_test_tmp/cache.db");
+ unlink("proj_test_tmp/ntf_r93.tif");
+ rmdir("proj_test_tmp");
+}
+
#endif
} // namespace