46 const size_t IDX_11kiB = 0;
47 const size_t IDX_65MiB = 1;
48 static std::vector<std::string> fname_payload_lst;
49 static std::vector<std::string> fname_payload_copy_lst;
50 static std::vector<uint64_t> fname_payload_size_lst;
51 const std::string url_input_root =
"http://localhost:8080/";
55 static bool add_test_file(
const std::string& name,
const size_t size_limit) {
62 static const std::string one_line =
"Hello World, this is a test and I like it. Exactly 100 characters long. 0123456780 abcdefghjklmnop..";
65 REQUIRE( ofs.
good() ==
true );
66 REQUIRE( ofs.
is_open() ==
true );
68 for(size=0; size < size_limit; size+=one_line.size()) {
69 if( one_line.size() != ofs.
write(one_line.data(), one_line.size()) ) {
70 ERR_PRINT(
"Write %zu bytes to test file failed: %s", one_line.size(), ofs.
to_string().c_str());
74 if( 1 != ofs.
write(
"X", 1) ) {
80 fname_payload_lst.push_back(name);
81 fname_payload_copy_lst.push_back(name+
".copy");
82 fname_payload_size_lst.push_back( size );
86 REQUIRE(
true == add_test_file(
"testfile_blob_01_11kiB.bin", (
size_t)(1024*11)) );
87 REQUIRE(
true == add_test_file(
"testfile_blob_02_65MiB.bin", (
size_t)(1024*1024*65)) );
90 static const data& get() {
99 const data& d = data::get();
105 int res = std::system(
"killall mini_httpd");
112 int res = std::system(
"killall mini_httpd");
115 const std::string cmd = std::string(
mini_httpd_exe)+
" -p 8080 -l "+cwd+
"/mini_httpd.log";
117 res = std::system(cmd.c_str());
127 if( output_stats.
exists() ) {
130 ERR_PRINT2(
"ByteStream copy failed: Failed deletion of existing output file %s", output_fname.c_str());
134 ERR_PRINT2(
"ByteStream copy failed: Not overwriting existing output file %s", output_fname.c_str());
141 ERR_PRINT2(
"ByteStream copy failed: Couldn't open output file %s", output_fname.c_str());
145 uint64_t out_bytes_payload = 0;
148 const size_t written = outfile.
write(data.data(), data.size());
149 out_bytes_payload += written;
150 return data.size() == written;
152 const size_t written = outfile.
write(data.data(), data.size());
153 out_bytes_payload += written;
158 io_buffer.reserve(buffer_size);
162 if ( 0==in_bytes_total || input.
fail() ) {
166 if ( outfile.
fail() ) {
167 IRQ_PRINT(
"ByteStream copy failed: Output file write failed in %s, out %s", input.
to_string().c_str(), outfile.
to_string().c_str());
186 if( http_support_expected ) {
187 REQUIRE( 0 < protos.size() );
189 REQUIRE( 0 == protos.size() );
192 const size_t file_idx = IDX_11kiB;
194 const std::string url =
"not_exiting_file.txt";
199 if(
nullptr != in ) {
200 jau::PLAIN_PRINT(
true,
"test00_protocols: not_exiting_file: %s", in->to_string().c_str());
202 REQUIRE(
nullptr == in );
205 const std::string url =
"file://not_exiting_file_uri.txt";
210 if(
nullptr != in ) {
211 jau::PLAIN_PRINT(
true,
"test00_protocols: not_exiting_file_uri: %s", in->to_string().c_str());
213 REQUIRE(
nullptr == in );
216 const std::string url =
"lala://localhost:8080/" + fname_payload_lst[file_idx];
221 if(
nullptr != in ) {
222 jau::PLAIN_PRINT(
true,
"test00_protocols: not_exiting_protocol_uri: %s", in->to_string().c_str());
224 REQUIRE(
nullptr == in );
227 const std::string url = url_input_root +
"not_exiting_http_uri.txt";
232 if( http_support_expected ) {
233 REQUIRE(
nullptr != in );
235 jau::PLAIN_PRINT(
true,
"test00_protocols: not_exiting_http_uri: %s", in->to_string().c_str());
236 REQUIRE(
false == in->good() );
237 REQUIRE(
true == in->fail() );
238 REQUIRE( 0 == in->content_size() );
240 REQUIRE(
nullptr == in );
250 const size_t file_idx = IDX_11kiB;
252 const std::string url = fname_payload_lst[file_idx];
257 if(
nullptr != in ) {
258 jau::PLAIN_PRINT(
true,
"test00_protocols: local-file-0: %s", in->to_string().c_str());
260 REQUIRE(
nullptr != in );
261 REQUIRE(
false == in->fail() );
263 bool res =
transfer(*in, fname_payload_copy_lst[file_idx]);
264 REQUIRE(
true == res );
267 REQUIRE(
true == out_stats.
exists() );
268 REQUIRE(
true == out_stats.
is_file() );
269 REQUIRE( in->content_size() == out_stats.
size() );
270 REQUIRE( fname_payload_size_lst[file_idx] == out_stats.
size() );
274 const std::string url =
"file://" + fname_payload_lst[file_idx];
279 if(
nullptr != in ) {
280 jau::PLAIN_PRINT(
true,
"test00_protocols: local-file-1: %s", in->to_string().c_str());
282 jau::PLAIN_PRINT(
true,
"test00_protocols: local-file-1: NULL from url '%s'", url.c_str());
284 REQUIRE(
nullptr != in );
285 REQUIRE(
false == in->fail() );
287 bool res =
transfer(*in, fname_payload_copy_lst[file_idx]);
288 REQUIRE(
true == res );
291 REQUIRE(
true == out_stats.
exists() );
292 REQUIRE(
true == out_stats.
is_file() );
293 REQUIRE( in->content_size() == out_stats.
size() );
294 REQUIRE( fname_payload_size_lst[file_idx] == out_stats.
size() );
298 const std::string url = url_input_root + fname_payload_lst[file_idx];
303 if(
nullptr != in ) {
304 jau::PLAIN_PRINT(
true,
"test00_protocols: http: %s", in->to_string().c_str());
306 if( http_support_expected ) {
307 REQUIRE(
nullptr != in );
308 REQUIRE(
false == in->fail() );
310 bool res =
transfer(*in, fname_payload_copy_lst[file_idx]);
311 REQUIRE(
true == res );
314 REQUIRE(
true == out_stats.
exists() );
315 REQUIRE(
true == out_stats.
is_file() );
316 REQUIRE( in->content_size() == out_stats.
size() );
317 REQUIRE( fname_payload_size_lst[file_idx] == out_stats.
size() );
320 REQUIRE(
nullptr == in );
327 const size_t file_idx = IDX_11kiB;
330 bool res =
transfer(data_stream, fname_payload_copy_lst[file_idx], 4096);
331 REQUIRE(
true == res );
334 REQUIRE(
true == out_stats.
exists() );
335 REQUIRE(
true == out_stats.
is_file() );
337 REQUIRE( fname_payload_size_lst[file_idx] == out_stats.
size() );
343 const size_t file_idx = IDX_65MiB;
346 bool res =
transfer(data_stream, fname_payload_copy_lst[file_idx], 4096);
347 REQUIRE(
true == res );
350 REQUIRE(
true == out_stats.
exists() );
351 REQUIRE(
true == out_stats.
is_file() );
353 REQUIRE( fname_payload_size_lst[file_idx] == out_stats.
size() );
359 const size_t file_idx = IDX_65MiB;
362 bool res =
transfer(data_stream, fname_payload_copy_lst[file_idx], 32768);
363 REQUIRE(
true == res );
366 REQUIRE(
true == out_stats.
exists() );
367 REQUIRE(
true == out_stats.
is_file() );
369 REQUIRE( fname_payload_size_lst[file_idx] == out_stats.
size() );
381 const size_t file_idx = IDX_11kiB;
383 const std::string uri_original = url_input_root + fname_payload_lst[file_idx];
387 bool res =
transfer(data_stream, fname_payload_copy_lst[file_idx], 32768);
388 REQUIRE(
true == res );
391 REQUIRE(
true == out_stats.
exists() );
392 REQUIRE(
true == out_stats.
is_file() );
394 REQUIRE( fname_payload_size_lst[file_idx] == out_stats.
size() );
398 const size_t file_idx = IDX_65MiB;
400 const std::string uri_original = url_input_root + fname_payload_lst[file_idx];
404 bool res =
transfer(data_stream, fname_payload_copy_lst[file_idx], 32768);
405 REQUIRE(
true == res );
408 REQUIRE(
true == out_stats.
exists() );
409 REQUIRE(
true == out_stats.
is_file() );
411 REQUIRE( fname_payload_size_lst[file_idx] == out_stats.
size() );
424 const size_t file_idx = IDX_11kiB;
426 const std::string uri_original = url_input_root +
"doesnt_exists.txt";
430 bool res =
transfer(data_stream, fname_payload_copy_lst[file_idx]);
431 REQUIRE(
false == res );
434 REQUIRE(
true == out_stats.
exists() );
435 REQUIRE(
true == out_stats.
is_file() );
436 REQUIRE( data_stream.
fail() ==
true );
439 REQUIRE( 0 == out_stats.
size() );
445 uint64_t xfer_total = 0;
447 uint8_t buffer[feed_size];
448 while( data_stream.
good() ) {
449 size_t count = data_stream.
read(buffer,
sizeof(buffer));
452 if( data_feed->
write(buffer, count) ) {
466 uint64_t xfer_total = 0;
470 uint8_t buffer[feed_size];
471 while( data_stream.
good() && xfer_total < file_size ) {
472 size_t count = data_stream.
read(buffer,
sizeof(buffer));
475 if( data_feed->
write(buffer, count) ) {
488 uint64_t xfer_total = 0;
492 uint8_t buffer[feed_size];
493 while( data_stream.
good() && xfer_total < file_size ) {
494 size_t count = data_stream.
read(buffer,
sizeof(buffer));
497 if( !data_feed->
write(buffer, count) ) {
507 uint64_t xfer_total = 0;
509 uint8_t buffer[feed_size];
510 while( data_stream.
good() ) {
511 size_t count = data_stream.
read(buffer,
sizeof(buffer));
514 if( data_feed->
write(buffer, count) ) {
515 if( xfer_total >= 1024 ) {
530 uint64_t xfer_total = 0;
534 uint8_t buffer[feed_size];
535 while( data_stream.
good() ) {
536 size_t count = data_stream.
read(buffer,
sizeof(buffer));
539 if( data_feed->
write(buffer, count) ) {
540 if( xfer_total >= file_size/4 ) {
555 const size_t buffer_size = 4096;
556 const size_t feed_size = 1024;
558 const size_t file_idx = IDX_11kiB;
562 std::thread feeder_thread= std::thread(&
feed_source_10, &data_feed, feed_size);
564 bool res =
transfer(data_feed, fname_payload_copy_lst[file_idx], buffer_size);
565 if( feeder_thread.joinable() ) {
566 feeder_thread.join();
568 REQUIRE(
true == res );
571 REQUIRE(
true == out_stats.
exists() );
572 REQUIRE(
true == out_stats.
is_file() );
574 REQUIRE( fname_payload_size_lst[file_idx] == out_stats.
size() );
580 std::thread feeder_thread= std::thread(&
feed_source_01, &data_feed, feed_size);
582 bool res =
transfer(data_feed, fname_payload_copy_lst[file_idx], buffer_size);
583 if( feeder_thread.joinable() ) {
584 feeder_thread.join();
586 REQUIRE(
true == res );
589 REQUIRE(
true == out_stats.
exists() );
590 REQUIRE(
true == out_stats.
is_file() );
592 REQUIRE( fname_payload_size_lst[file_idx] == out_stats.
size() );
598 std::thread feeder_thread= std::thread(&
feed_source_00, &data_feed, feed_size);
600 bool res =
transfer(data_feed, fname_payload_copy_lst[file_idx], buffer_size);
601 if( feeder_thread.joinable() ) {
602 feeder_thread.join();
604 REQUIRE(
true == res );
607 REQUIRE(
true == out_stats.
exists() );
608 REQUIRE(
true == out_stats.
is_file() );
610 REQUIRE( fname_payload_size_lst[file_idx] == out_stats.
size() );
615 const size_t file_idx = IDX_65MiB;
619 std::thread feeder_thread= std::thread(&
feed_source_10, &data_feed, feed_size);
621 bool res =
transfer(data_feed, fname_payload_copy_lst[file_idx], buffer_size);
622 if( feeder_thread.joinable() ) {
623 feeder_thread.join();
625 REQUIRE(
true == res );
628 REQUIRE(
true == out_stats.
exists() );
629 REQUIRE(
true == out_stats.
is_file() );
631 REQUIRE( fname_payload_size_lst[file_idx] == out_stats.
size() );
639 const size_t buffer_size = 32768;
640 const size_t feed_size = 32768;
642 const size_t file_idx = IDX_11kiB;
646 std::thread feeder_thread= std::thread(&
feed_source_10, &data_feed, feed_size);
648 bool res =
transfer(data_feed, fname_payload_copy_lst[file_idx], buffer_size);
649 if( feeder_thread.joinable() ) {
650 feeder_thread.join();
652 REQUIRE(
true == res );
655 REQUIRE(
true == out_stats.
exists() );
656 REQUIRE(
true == out_stats.
is_file() );
658 REQUIRE( fname_payload_size_lst[file_idx] == out_stats.
size() );
664 std::thread feeder_thread= std::thread(&
feed_source_01, &data_feed, feed_size);
666 bool res =
transfer(data_feed, fname_payload_copy_lst[file_idx], buffer_size);
667 if( feeder_thread.joinable() ) {
668 feeder_thread.join();
670 REQUIRE(
true == res );
673 REQUIRE(
true == out_stats.
exists() );
674 REQUIRE(
true == out_stats.
is_file() );
676 REQUIRE( fname_payload_size_lst[file_idx] == out_stats.
size() );
682 std::thread feeder_thread= std::thread(&
feed_source_00, &data_feed, feed_size);
684 bool res =
transfer(data_feed, fname_payload_copy_lst[file_idx], buffer_size);
685 if( feeder_thread.joinable() ) {
686 feeder_thread.join();
688 REQUIRE(
true == res );
691 REQUIRE(
true == out_stats.
exists() );
692 REQUIRE(
true == out_stats.
is_file() );
694 REQUIRE( fname_payload_size_lst[file_idx] == out_stats.
size() );
702 const size_t buffer_size = 32768;
703 const size_t feed_size = 32768;
705 const size_t file_idx = IDX_65MiB;
709 std::thread feeder_thread= std::thread(&
feed_source_10, &data_feed, feed_size);
711 bool res =
transfer(data_feed, fname_payload_copy_lst[file_idx], buffer_size);
712 if( feeder_thread.joinable() ) {
713 feeder_thread.join();
715 REQUIRE(
true == res );
718 REQUIRE(
true == out_stats.
exists() );
719 REQUIRE(
true == out_stats.
is_file() );
721 REQUIRE( fname_payload_size_lst[file_idx] == out_stats.
size() );
729 const size_t buffer_size = 4096;
730 const size_t feed_size = 1024;
732 const size_t file_idx = IDX_65MiB;
736 std::thread feeder_thread= std::thread(&
feed_source_20, &data_feed, feed_size);
738 bool res =
transfer(data_feed, fname_payload_copy_lst[file_idx], buffer_size);
739 if( feeder_thread.joinable() ) {
740 feeder_thread.join();
742 REQUIRE(
false == res );
745 REQUIRE(
true == out_stats.
exists() );
746 REQUIRE(
true == out_stats.
is_file() );
749 REQUIRE( fname_payload_size_lst[file_idx] > out_stats.
size() );
755 std::thread feeder_thread= std::thread(&
feed_source_21, &data_feed, feed_size);
757 bool res =
transfer(data_feed, fname_payload_copy_lst[file_idx], buffer_size);
758 if( feeder_thread.joinable() ) {
759 feeder_thread.join();
761 REQUIRE(
false == res );
764 REQUIRE(
true == out_stats.
exists() );
765 REQUIRE(
true == out_stats.
is_file() );
767 REQUIRE( fname_payload_size_lst[file_idx] == data_feed.
content_size() );
776std::vector<std::string> TestByteStream01::fname_payload_lst;
777std::vector<std::string> TestByteStream01::fname_payload_copy_lst;
778std::vector<uint64_t> TestByteStream01::fname_payload_size_lst;
static void feed_source_00(jau::io::ByteInStream_Feed *data_feed, const size_t feed_size=1024)
static void feed_source_20(jau::io::ByteInStream_Feed *data_feed, const size_t feed_size=1024)
static bool transfer(jau::io::ByteInStream &input, const std::string &output_fname, const size_t buffer_size=4096)
void test04_copy_file_ok_65MiB_buff32k()
static void httpd_start()
void test11_copy_http_ok_buff32k()
static void feed_source_01(jau::io::ByteInStream_Feed *data_feed, const size_t feed_size=1024)
void test22_copy_fed_ok_buff32k()
void test20_copy_fed_ok_buff4k_feed1k()
void test01_copy_file_ok_11kiB_buff4k()
void test23_copy_fed_irq()
void test00a_protocols_error()
void test02_copy_file_ok_65MiB_buff4k()
void test21_copy_fed_ok_buff32k()
void test12_copy_http_404()
static void feed_source_10(jau::io::ByteInStream_Feed *data_feed, const size_t feed_size=1024)
static void feed_source_21(jau::io::ByteInStream_Feed *data_feed, const size_t feed_size=1024)
void test00b_protocols_ok()
Platform agnostic representation of POSIX ::lstat() and ::stat() for a given pathname.
constexpr bool exists() const noexcept
Returns true if entity does not exist, exclusive bit.
constexpr bool is_file() const noexcept
Returns true if entity is a file, might be in combination with is_link().
uint64_t size() const noexcept
Returns the size in bytes of this element if is_file(), otherwise zero.
std::string path() const noexcept
Returns the unix path representation.
Class template jau::function is a general-purpose static-polymorphic function wrapper.
Ringbuffer-Based byte input stream with an externally provisioned data feed.
void set_content_size(const uint64_t size) noexcept
Set known content size, informal only.
bool has_content_size() const noexcept override
Returns true if implementation is aware of content_size(), otherwise false.
void set_eof(const async_io_result_t result) noexcept
Set end-of-data (EOS), i.e.
bool write(uint8_t in[], size_t length, const jau::fraction_i64 &timeout) noexcept
Write given bytes to the async ringbuffer using explicit given timeout.
uint64_t content_size() const noexcept override
Returns the content_size if known.
std::string id() const noexcept override
return the id of this data source
File based byte input stream, including named file descriptor.
uint64_t content_size() const noexcept override
Returns the content_size if known.
size_t read(void *, size_t) noexcept override
Read from the source.
std::string id() const noexcept override
return the id of this data source
Ringbuffer-Based byte input stream with a URL connection provisioned data feed.
uint64_t content_size() const noexcept override
Returns the content_size if known.
bool has_content_size() const noexcept override
Returns true if implementation is aware of content_size(), otherwise false.
Abstract byte input stream object.
virtual void close() noexcept=0
Close the stream if supported by the underlying mechanism.
virtual bool has_content_size() const noexcept=0
Returns true if implementation is aware of content_size(), otherwise false.
virtual uint64_t content_size() const noexcept=0
Returns the content_size if known.
virtual std::string to_string() const noexcept=0
File based byte output stream, including named file descriptor.
size_t write(const void *, size_t) noexcept override
Write to the data sink.
std::string to_string() const noexcept override
bool is_open() const noexcept override
Checks if the stream has an associated file.
bool fail() const noexcept
Checks if an error has occurred.
bool good() const noexcept
Checks if no error nor eof() has occurred i.e.
#define ERR_PRINT(...)
Use for unconditional error messages, prefix '[elapsed_time] Error @ FILE:LINE FUNC: '.
#define ERR_PRINT2(...)
Use for unconditional error messages, prefix '[elapsed_time] Error @ FILE:LINE FUNC: '.
#define IRQ_PRINT(...)
Use for unconditional interruption messages, prefix '[elapsed_time] Interrupted @ FILE:LINE FUNC: '.
std::string to_string(const endian_t v) noexcept
Return std::string representation of the given endian.
std::string get_cwd() noexcept
Return the current working directory or empty on failure.
bool compare(const file_stats &source1, const file_stats &source2, const bool verbose=false) noexcept
Compare the bytes of both files, denoted by source1 and source2.
bool remove(const std::string &path, const traverse_options topts=traverse_options::none) noexcept
Remove the given path.
bool to_fraction_i64(fraction_i64 &result, const std::string &value, const fraction_i64 &min_allowed, const fraction_i64 &max_allowed) noexcept
Stores the fraction_i64 value of the given string value in format <num>/<denom>, which may contain wh...
fraction_timespec getMonotonicTime() noexcept
Returns current monotonic time since Unix Epoch 00:00:00 UTC on 1970-01-01.
std::vector< T, jau::callocator_sec< T > > secure_vector
std::unique_ptr< ByteInStream > to_ByteInStream(const std::string &path_or_uri, jau::fraction_i64 timeout=20_s) noexcept
Parses the given path_or_uri, if it matches a supported protocol, see jau::io::uri::protocol_supporte...
bool is_local_file_protocol(const std::string_view &uri) noexcept
Returns true if the uri-scheme of given uri matches the local file protocol, i.e.
uint64_t read_stream(ByteInStream &in, secure_vector< uint8_t > &buffer, const StreamConsumerFunc &consumer_fn) noexcept
Synchronous byte input stream reader using the given StreamConsumerFunc consumer_fn.
std::vector< std::string_view > supported_protocols() noexcept
Returns a list of supported protocol supported by libcurl network protocols, queried at runtime.
void print_stats(const std::string &prefix, const uint64_t &out_bytes_total, const jau::fraction_i64 &td) noexcept
bool protocol_supported(const std::string_view &uri) noexcept
Returns true if the uri-scheme of given uri matches a supported by libcurl network protocols otherwis...
@ FAILED
Operation failed.
@ SUCCESS
Operation succeeded.
void PLAIN_PRINT(const bool printPrefix, const char *format,...) noexcept
Use for unconditional plain messages, prefix '[elapsed_time] ' if printPrefix == true.
int fprintf_td(const uint64_t elapsed_ms, FILE *stream, const char *format,...) noexcept
Convenient fprintf() invocation, prepending the given elapsed_ms timestamp.
bool sleep_for(const fraction_timespec &relative_time, const bool monotonic=true, const bool ignore_irq=true) noexcept
sleep_for causes the current thread to block until a specific amount of time has passed.
Timespec structure using int64_t for its components in analogy to struct timespec_t on 64-bit platfor...
METHOD_AS_TEST_CASE(TestByteStream01::test00a_protocols_error, "test00a_protocols_error")
constexpr std::string_view mini_httpd_exe