]> git.proxmox.com Git - ceph.git/blobdiff - ceph/src/seastar/tests/unit/fstream_test.cc
update source to Ceph Pacific 16.2.2
[ceph.git] / ceph / src / seastar / tests / unit / fstream_test.cc
index dacd1b40ad6adab80fcda29afa8e6d6623ed33fc..9f15b27d3956b04f51559f7c8ae31126affa33f2 100644 (file)
 #include <algorithm>
 #include <iostream>
 #include <numeric>
-#include <seastar/core/reactor.hh>
 #include <seastar/core/fstream.hh>
+#include <seastar/core/smp.hh>
 #include <seastar/core/shared_ptr.hh>
 #include <seastar/core/app-template.hh>
 #include <seastar/core/do_with.hh>
 #include <seastar/core/seastar.hh>
+#include <seastar/core/semaphore.hh>
 #include <seastar/testing/test_case.hh>
 #include <seastar/testing/test_runner.hh>
 #include <seastar/core/thread.hh>
 #include <seastar/core/print.hh>
 #include <seastar/util/defer.hh>
+#include <seastar/util/tmp_file.hh>
 #include <boost/range/adaptor/transformed.hpp>
 #include <boost/algorithm/cxx11/any_of.hpp>
 #include "mock_file.hh"
+#include <boost/range/irange.hpp>
 
 using namespace seastar;
+namespace fs = std::filesystem;
 
 struct writer {
     output_stream<char> out;
-    writer(file f) : out(make_file_output_stream(std::move(f))) {}
+    static future<shared_ptr<writer>> make(file f) {
+        return api_v3::and_newer::make_file_output_stream(std::move(f)).then([] (output_stream<char>&& os) {
+            return make_shared<writer>(writer{std::move(os)});
+        });
+    }
 };
 
 struct reader {
@@ -51,66 +59,64 @@ struct reader {
 };
 
 SEASTAR_TEST_CASE(test_fstream) {
-    auto sem = make_lw_shared<semaphore>(0);
-
-        // Run in background, signal when done.
-        (void)open_file_dma("testfile.tmp",
-                      open_flags::rw | open_flags::create | open_flags::truncate).then([sem] (file f) {
-            auto w = make_shared<writer>(std::move(f));
-            auto buf = static_cast<char*>(::malloc(4096));
-            memset(buf, 0, 4096);
-            buf[0] = '[';
-            buf[1] = 'A';
-            buf[4095] = ']';
-            return w->out.write(buf, 4096).then([buf, w] {
-                ::free(buf);
-                return make_ready_future<>();
-            }).then([w] {
-                auto buf = static_cast<char*>(::malloc(8192));
-                memset(buf, 0, 8192);
+    return tmp_dir::do_with([] (tmp_dir& t) {
+        auto filename = (t.get_path() / "testfile.tmp").native();
+        return open_file_dma(filename,
+                open_flags::rw | open_flags::create | open_flags::truncate).then([filename] (file f) {
+            return writer::make(std::move(f)).then([filename] (shared_ptr<writer> w) {
+                auto buf = static_cast<char*>(::malloc(4096));
+                memset(buf, 0, 4096);
                 buf[0] = '[';
-                buf[1] = 'B';
-                buf[8191] = ']';
-                return w->out.write(buf, 8192).then([buf, w] {
+                buf[1] = 'A';
+                buf[4095] = ']';
+                return w->out.write(buf, 4096).then([buf, w] {
                     ::free(buf);
-                    return w->out.close().then([w] {});
-                });
-            }).then([] {
-                return open_file_dma("testfile.tmp", open_flags::ro);
-            }).then([] (file f) {
-                /*  file content after running the above:
-                 * 00000000  5b 41 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |[A..............|
-                 * 00000010  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
-                 * *
-                 * 00000ff0  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 5d  |...............]|
-                 * 00001000  5b 42 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |[B..............|
-                 * 00001010  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
-                 * *
-                 * 00002ff0  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 5d  |...............]|
-                 * 00003000
-                 */
-                auto r = make_shared<reader>(std::move(f));
-                return r->in.read_exactly(4096 + 8192).then([r] (temporary_buffer<char> buf) {
-                    auto p = buf.get();
-                    BOOST_REQUIRE(p[0] == '[' && p[1] == 'A' && p[4095] == ']');
-                    BOOST_REQUIRE(p[4096] == '[' && p[4096 + 1] == 'B' && p[4096 + 8191] == ']');
                     return make_ready_future<>();
-                }).then([r] {
-                    return r->in.close();
-                }).finally([r] {});
-            }).finally([sem] () {
-                sem->signal();
+                }).then([w] {
+                    auto buf = static_cast<char*>(::malloc(8192));
+                    memset(buf, 0, 8192);
+                    buf[0] = '[';
+                    buf[1] = 'B';
+                    buf[8191] = ']';
+                    return w->out.write(buf, 8192).then([buf, w] {
+                        ::free(buf);
+                        return w->out.close().then([w] {});
+                    });
+                }).then([filename] {
+                    return open_file_dma(filename, open_flags::ro);
+                }).then([] (file f) {
+                    /*  file content after running the above:
+                     * 00000000  5b 41 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |[A..............|
+                     * 00000010  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
+                     * *
+                     * 00000ff0  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 5d  |...............]|
+                     * 00001000  5b 42 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |[B..............|
+                     * 00001010  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
+                     * *
+                     * 00002ff0  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 5d  |...............]|
+                     * 00003000
+                     */
+                    auto r = make_shared<reader>(std::move(f));
+                    return r->in.read_exactly(4096 + 8192).then([r] (temporary_buffer<char> buf) {
+                        auto p = buf.get();
+                        BOOST_REQUIRE(p[0] == '[' && p[1] == 'A' && p[4095] == ']');
+                        BOOST_REQUIRE(p[4096] == '[' && p[4096 + 1] == 'B' && p[4096 + 8191] == ']');
+                        return make_ready_future<>();
+                    }).then([r] {
+                        return r->in.close();
+                    }).finally([r] {});
+                });
             });
         });
-
-    return sem->wait();
+    });
 }
 
 SEASTAR_TEST_CASE(test_consume_skip_bytes) {
-    return seastar::async([] {
-        auto f = open_file_dma("testfile.tmp",
+    return tmp_dir::do_with_thread([] (tmp_dir& t) {
+        auto filename = (t.get_path() / "testfile.tmp").native();
+        auto f = open_file_dma(filename,
                                open_flags::rw | open_flags::create | open_flags::truncate).get0();
-        auto w = make_lw_shared<writer>(std::move(f));
+        auto w = writer::make(std::move(f)).get0();
         auto write_block = [w] (char c, size_t size) {
             std::vector<char> vec(size, c);
             w->out.write(&vec.front(), vec.size()).get();
@@ -125,7 +131,7 @@ SEASTAR_TEST_CASE(test_consume_skip_bytes) {
          * *
          * 00004000
          */
-        f = open_file_dma("testfile.tmp", open_flags::ro).get0();
+        f = open_file_dma(filename, open_flags::ro).get0();
         auto r = make_lw_shared<reader>(std::move(f), file_input_stream_options{512});
         struct consumer {
             uint64_t _count = 0;
@@ -175,58 +181,59 @@ SEASTAR_TEST_CASE(test_consume_skip_bytes) {
 }
 
 SEASTAR_TEST_CASE(test_fstream_unaligned) {
-    auto sem = make_lw_shared<semaphore>(0);
-
-    // Run in background, signal when done.
-    (void)open_file_dma("testfile.tmp",
-                  open_flags::rw | open_flags::create | open_flags::truncate).then([sem] (file f) {
-        auto w = make_shared<writer>(std::move(f));
-        auto buf = static_cast<char*>(::malloc(40));
-        memset(buf, 0, 40);
-        buf[0] = '[';
-        buf[1] = 'A';
-        buf[39] = ']';
-        return w->out.write(buf, 40).then([buf, w] {
-            ::free(buf);
-            return w->out.close().then([w] {});
-        }).then([] {
-            return open_file_dma("testfile.tmp", open_flags::ro);
-        }).then([] (file f) {
-            return do_with(std::move(f), [] (file& f) {
-                return f.size().then([] (size_t size) {
-                    // assert that file was indeed truncated to the amount of bytes written.
-                    BOOST_REQUIRE(size == 40);
-                    return make_ready_future<>();
+  return tmp_dir::do_with([] (tmp_dir& t) {
+    auto filename = (t.get_path() / "testfile.tmp").native();
+    return open_file_dma(filename,
+            open_flags::rw | open_flags::create | open_flags::truncate).then([filename] (file f) {
+        return writer::make(std::move(f)).then([filename] (shared_ptr<writer> w) {
+            auto buf = static_cast<char*>(::malloc(40));
+            memset(buf, 0, 40);
+            buf[0] = '[';
+            buf[1] = 'A';
+            buf[39] = ']';
+            return w->out.write(buf, 40).then([buf, w] {
+                ::free(buf);
+                return w->out.close().then([w] {});
+            }).then([filename] {
+                return open_file_dma(filename, open_flags::ro);
+            }).then([] (file f) {
+                return do_with(std::move(f), [] (file& f) {
+                    return f.size().then([] (size_t size) {
+                        // assert that file was indeed truncated to the amount of bytes written.
+                        BOOST_REQUIRE(size == 40);
+                        return make_ready_future<>();
+                    });
                 });
+            }).then([filename] {
+                return open_file_dma(filename, open_flags::ro);
+            }).then([] (file f) {
+                auto r = make_shared<reader>(std::move(f));
+                return r->in.read_exactly(40).then([r] (temporary_buffer<char> buf) {
+                    auto p = buf.get();
+                    BOOST_REQUIRE(p[0] == '[' && p[1] == 'A' && p[39] == ']');
+                    return make_ready_future<>();
+                }).then([r] {
+                    return r->in.close();
+                }).finally([r] {});
             });
-        }).then([] {
-            return open_file_dma("testfile.tmp", open_flags::ro);
-        }).then([] (file f) {
-            auto r = make_shared<reader>(std::move(f));
-            return r->in.read_exactly(40).then([r] (temporary_buffer<char> buf) {
-                auto p = buf.get();
-                BOOST_REQUIRE(p[0] == '[' && p[1] == 'A' && p[39] == ']');
-                return make_ready_future<>();
-            }).then([r] {
-                return r->in.close();
-            }).finally([r] {});
-        }).finally([sem] () {
-            sem->signal();
         });
     });
-
-    return sem->wait();
+  });
 }
 
 future<> test_consume_until_end(uint64_t size) {
-    return open_file_dma("testfile.tmp",
+  return tmp_dir::do_with([size] (tmp_dir& t) {
+    auto filename = (t.get_path() / "testfile.tmp").native();
+    return open_file_dma(filename,
             open_flags::rw | open_flags::create | open_flags::truncate).then([size] (file f) {
-            return do_with(make_file_output_stream(f), [size] (output_stream<char>& out) {
+          return api_v3::and_newer::make_file_output_stream(f).then([size] (output_stream<char>&& os) {
+            return do_with(std::move(os), [size] (output_stream<char>& out) {
                 std::vector<char> buf(size);
                 std::iota(buf.begin(), buf.end(), 0);
                 return out.write(buf.data(), buf.size()).then([&out] {
                    return out.flush();
                 });
+          });
             }).then([f] {
                 return f.size();
             }).then([size, f] (size_t real_size) {
@@ -241,7 +248,7 @@ future<> test_consume_until_end(uint64_t size) {
                     std::iota(expected.begin(), expected.end(), offset);
                     offset += buf.size();
                     BOOST_REQUIRE(std::equal(buf.begin(), buf.end(), expected.begin()));
-                    return make_ready_future<input_stream<char>::unconsumed_remainder>(compat::nullopt);
+                    return make_ready_future<input_stream<char>::unconsumed_remainder>(std::nullopt);
                 };
                 return do_with(make_file_input_stream(f), std::move(consumer), [] (input_stream<char>& in, auto& consumer) {
                     return in.consume(consumer).then([&in] {
@@ -249,9 +256,10 @@ future<> test_consume_until_end(uint64_t size) {
                     });
                 });
             }).finally([f] () mutable {
-                return f.close().finally([f]{});
+                return f.close();
             });
     });
+  });
 }
 
 
@@ -272,16 +280,17 @@ SEASTAR_TEST_CASE(test_consume_unaligned_file_large) {
 }
 
 SEASTAR_TEST_CASE(test_input_stream_esp_around_eof) {
-    return seastar::async([] {
+    return tmp_dir::do_with_thread([] (tmp_dir& t) {
         auto flen = uint64_t(5341);
         auto rdist = std::uniform_int_distribution<char>();
         auto reng = testing::local_random_engine;
         auto data = boost::copy_range<std::vector<uint8_t>>(
                 boost::irange<uint64_t>(0, flen)
                 | boost::adaptors::transformed([&] (int x) { return rdist(reng); }));
-        auto f = open_file_dma("file.tmp",
+        auto filename = (t.get_path() / "testfile.tmp").native();
+        auto f = open_file_dma(filename,
                 open_flags::rw | open_flags::create | open_flags::truncate).get0();
-        auto out = make_file_output_stream(f);
+        auto out = api_v3::and_newer::make_file_output_stream(f).get0();
         out.write(reinterpret_cast<const char*>(data.data()), data.size()).get();
         out.flush().get();
         //out.close().get();  // FIXME: closes underlying stream:?!
@@ -333,9 +342,22 @@ SEASTAR_TEST_CASE(test_input_stream_esp_around_eof) {
     });
 }
 
+#if SEASTAR_API_LEVEL >= 3
+SEASTAR_TEST_CASE(without_api_prefix) {
+    return tmp_dir::do_with_thread([](tmp_dir& t) {
+        auto filename = (t.get_path() / "testfile.tmp").native();
+        auto f = open_file_dma(filename,
+                open_flags::rw | open_flags::create | open_flags::truncate).get0();
+        output_stream<char> out = make_file_output_stream(f).get0();
+        out.close().get();
+    });
+}
+#endif
+
 SEASTAR_TEST_CASE(file_handle_test) {
-    return seastar::async([] {
-        auto f = open_file_dma("testfile.tmp", open_flags::create | open_flags::truncate | open_flags::rw).get0();
+    return tmp_dir::do_with_thread([] (tmp_dir& t) {
+        auto filename = (t.get_path() / "testfile.tmp").native();
+        auto f = open_file_dma(filename, open_flags::create | open_flags::truncate | open_flags::rw).get0();
         auto buf = static_cast<char*>(aligned_alloc(4096, 4096));
         auto del = defer([&] { ::free(buf); });
         for (unsigned i = 0; i < 4096; ++i) {
@@ -350,7 +372,7 @@ SEASTAR_TEST_CASE(file_handle_test) {
                 auto del = defer([&] { ::free(buf); });
                 f.dma_read(0, buf, 4096).get();
                 for (unsigned i = 0; i < 4096; ++i) {
-                    bad[engine().cpu_id()] |= buf[i] != char(i);
+                    bad[this_shard_id()] |= buf[i] != char(i);
                 }
             });
         }).get();
@@ -377,7 +399,7 @@ SEASTAR_TEST_CASE(test_fstream_slow_start) {
         static constexpr size_t requests_at_slow_start = 2; // 1 request + 1 read-ahead
         static constexpr size_t requests_at_full_speed = read_ahead + 1; // 1 request + read_ahead
 
-        compat::optional<size_t> initial_read_size;
+        std::optional<size_t> initial_read_size;
 
         auto read_whole_file_with_slow_start = [&] (auto fstr) {
             uint64_t total_read = 0;
@@ -486,6 +508,7 @@ SEASTAR_TEST_CASE(test_fstream_slow_start) {
         auto make_fstream = [&] {
             struct fstream_wrapper {
                 input_stream<char> s;
+                explicit fstream_wrapper(input_stream<char>&& s) : s(std::move(s)) {}
                 fstream_wrapper(fstream_wrapper&&) = default;
                 fstream_wrapper& operator=(fstream_wrapper&&) = default;
                 future<temporary_buffer<char>> read() {
@@ -498,7 +521,7 @@ SEASTAR_TEST_CASE(test_fstream_slow_start) {
                     s.close().get();
                 }
             };
-            return fstream_wrapper{make_file_input_stream(file(mock_file), 0, file_size, options)};
+            return fstream_wrapper(make_file_input_stream(file(mock_file), 0, file_size, options));
         };
 
         BOOST_TEST_MESSAGE("Reading file, no history, expectiong a slow start");