agent-enviroments/builder/libs/seastar/tests/unit/fsnotifier_test.cc
2024-09-10 17:06:08 +03:00

229 lines
6.6 KiB
C++

/*
* This file is open source software, licensed to you under the terms
* of the Apache License, Version 2.0 (the "License"). See the NOTICE file
* distributed with this work for additional information regarding copyright
* ownership. You may not use this file except in compliance with the License.
*
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
/*
* Copyright (C) 2020 ScyllaDB Ltd.
*/
#include <random>
#include <algorithm>
#include <seastar/testing/thread_test_case.hh>
#include <seastar/core/fstream.hh>
#include <seastar/core/file.hh>
#include <seastar/core/seastar.hh>
#include <seastar/util/std-compat.hh>
#include <seastar/core/fsnotify.hh>
#include "tmpdir.hh"
namespace fs = std::filesystem;
using namespace seastar;
using experimental::fsnotifier;
static bool find_event(const std::vector<fsnotifier::event>& events, const fsnotifier::watch& w, fsnotifier::flags mask, std::optional<sstring> path = {}) {
auto i = std::find_if(events.begin(), events.end(), [&](const fsnotifier::event& e) {
return (e.mask & mask) != fsnotifier::flags{}
&& e.id == w
&& (!path || *path == e.name)
;
});
return i != events.end();
}
SEASTAR_THREAD_TEST_CASE(test_notify_modify_close_delete) {
tmpdir tmp;
fsnotifier fsn;
auto p = tmp.path() / "kossa.dat";
auto f = open_file_dma(p.native(), open_flags::create|open_flags::rw).get();
auto w = fsn.create_watch(p.native(), fsnotifier::flags::delete_self
| fsnotifier::flags::modify
| fsnotifier::flags::close
).get();
auto os = make_file_output_stream(f).get();
os.write("kossa").get();
os.flush().get();
{
auto events = fsn.wait().get();
BOOST_REQUIRE(find_event(events, w, fsnotifier::flags::modify));
}
os.close().get();
{
auto events = fsn.wait().get();
BOOST_REQUIRE(find_event(events, w, fsnotifier::flags::close_write));
}
remove_file(p.native()).get();
{
auto events = fsn.wait().get();
BOOST_REQUIRE(find_event(events, w, fsnotifier::flags::delete_self));
BOOST_REQUIRE(find_event(events, w, fsnotifier::flags::ignored));
}
}
SEASTAR_THREAD_TEST_CASE(test_notify_overwrite) {
tmpdir tmp;
fsnotifier fsn;
auto p = tmp.path() / "kossa.dat";
auto write_file = [](fs::path& p, sstring content) {
auto f = open_file_dma(p.native(), open_flags::create|open_flags::rw).get();
auto os = make_file_output_stream(f).get();
os.write(content).get();
os.flush().get();
os.close().get();
};
write_file(p, "kossa");
auto w = fsn.create_watch(p.native(), fsnotifier::flags::delete_self
| fsnotifier::flags::modify
| fsnotifier::flags::close
).get();
write_file(p, "kossabello");
{
auto events = fsn.wait().get();
BOOST_REQUIRE(find_event(events, w, fsnotifier::flags::modify));
}
write_file(p, "kossaruffalobill");
{
auto events = fsn.wait().get();
BOOST_REQUIRE(find_event(events, w, fsnotifier::flags::modify));
}
auto p2 = tmp.path() / "tmp.apa";
write_file(p2, "le apa");
auto w2 = fsn.create_watch(tmp.path().native(), fsnotifier::flags::move_to).get();
rename_file(p2.native(), p.native()).get();
{
auto events = fsn.wait().get();
BOOST_REQUIRE(find_event(events, w, fsnotifier::flags::delete_self));
BOOST_REQUIRE(find_event(events, w2, fsnotifier::flags::move_to, p.filename().native()));
}
}
SEASTAR_THREAD_TEST_CASE(test_notify_create_delete_child) {
tmpdir tmp;
fsnotifier fsn;
auto p = tmp.path() / "kossa.dat";
auto w = fsn.create_watch(tmp.path().native(), fsnotifier::flags::create_child
| fsnotifier::flags::delete_child
).get();
auto f = open_file_dma(p.native(), open_flags::create|open_flags::rw).get();
{
auto events = fsn.wait().get();
BOOST_REQUIRE(find_event(events, w, fsnotifier::flags::create_child));
}
f.close().get();
remove_file(p.native()).get();
{
auto events = fsn.wait().get();
BOOST_REQUIRE(find_event(events, w, fsnotifier::flags::delete_child));
BOOST_REQUIRE(!find_event(events, w, fsnotifier::flags::ignored));
}
}
SEASTAR_THREAD_TEST_CASE(test_notify_open) {
tmpdir tmp;
fsnotifier fsn;
auto p = tmp.path() / "kossa.dat";
auto f = open_file_dma(p.native(), open_flags::create|open_flags::rw).get();
f.close().get();
auto w = fsn.create_watch(p.native(), fsnotifier::flags::open).get();
auto f2 = open_file_dma(p.native(), open_flags::ro).get();
{
auto events = fsn.wait().get();
BOOST_REQUIRE(find_event(events, w, fsnotifier::flags::open));
}
f2.close().get();
}
SEASTAR_THREAD_TEST_CASE(test_notify_move) {
tmpdir tmp;
fsnotifier fsn;
auto p = tmp.path() / "kossa.dat";
auto f = open_file_dma(p.native(), open_flags::create|open_flags::rw).get();
f.close().get();
auto w = fsn.create_watch(tmp.path().native(), fsnotifier::flags::move).get();
auto p2 = tmp.path() / "kossa.mu";
rename_file(p.native(), p2.native()).get();
{
auto events = fsn.wait().get();
BOOST_REQUIRE(find_event(events, w, fsnotifier::flags::move_from, p.filename().native()));
BOOST_REQUIRE(find_event(events, w, fsnotifier::flags::move_to, p2.filename().native()));
}
tmpdir tmp2;
auto p3 = tmp2.path() / "ninja.mission";
auto w2 = fsn.create_watch(tmp2.path().native(), fsnotifier::flags::move).get();
rename_file(p2.native(), p3.native()).get();
{
auto events = fsn.wait().get();
BOOST_REQUIRE(find_event(events, w, fsnotifier::flags::move_from, p2.filename().native()));
BOOST_REQUIRE(find_event(events, w2, fsnotifier::flags::move_to, p3.filename().native()));
}
}
SEASTAR_THREAD_TEST_CASE(test_shutdown_notifier) {
tmpdir tmp;
fsnotifier fsn;
auto p = tmp.path() / "kossa.dat";
auto f = open_file_dma(p.native(), open_flags::create|open_flags::rw).get();
f.close().get();
auto w = fsn.create_watch(tmp.path().native(), fsnotifier::flags::delete_child).get();
auto fut = fsn.wait();
fsn.shutdown();
auto events = fut.get();
BOOST_REQUIRE(events.empty());
}