mirror of https://github.com/tstack/lnav.git
[remote] add some tailer tests
This commit is contained in:
parent
5ab5d9a4f4
commit
1737964df6
|
@ -71,6 +71,7 @@ LAST_TEST=""
|
|||
#
|
||||
run_test() {
|
||||
LAST_TEST="test: $@"
|
||||
export test_num=`expr ${test_num} \+ 1`
|
||||
"$@" > ${test_file_base}_${test_num}.tmp 2> ${test_file_base}_${test_num}.err
|
||||
}
|
||||
|
||||
|
@ -90,6 +91,10 @@ run_test() {
|
|||
# EOF
|
||||
#
|
||||
check_output() {
|
||||
sed -i "" \
|
||||
-e "s;${test_dir};{test_dir};g" \
|
||||
-e "s;${top_srcdir};{top_srcdir};g" \
|
||||
${test_file_base}_${test_num}.tmp
|
||||
diff -w -u - ${test_file_base}_${test_num}.tmp > ${test_file_base}_${test_num}.diff
|
||||
if test $? -ne 0; then
|
||||
echo $LAST_TEST
|
||||
|
@ -97,7 +102,6 @@ check_output() {
|
|||
cat ${test_file_base}_${test_num}.diff
|
||||
exit 1
|
||||
fi
|
||||
test_num=`expr ${test_num} \+ 1`
|
||||
}
|
||||
|
||||
check_output_ws() {
|
||||
|
@ -108,7 +112,6 @@ check_output_ws() {
|
|||
cat ${test_file_base}_${test_num}.diff
|
||||
exit 1
|
||||
fi
|
||||
test_num=`expr ${test_num} \+ 1`
|
||||
}
|
||||
|
||||
test_filename() {
|
||||
|
@ -120,6 +123,10 @@ test_err_filename() {
|
|||
}
|
||||
|
||||
check_error_output() {
|
||||
sed -i "" \
|
||||
-e "s;${test_dir};{test_dir};g" \
|
||||
-e "s;${top_srcdir};{top_srcdir};g" \
|
||||
${test_file_base}_${test_num}.err
|
||||
diff -w -u - ${test_file_base}_${test_num}.err \
|
||||
> ${test_file_base}_${test_num}.err.diff
|
||||
if test $? -ne 0; then
|
||||
|
@ -150,7 +157,6 @@ grep_output_for() {
|
|||
echo "${test_file_base}_${test_num}.tmp: $2"
|
||||
exit 1
|
||||
fi
|
||||
test_num=`expr ${test_num} \+ 1`
|
||||
}
|
||||
|
||||
on_error_log() {
|
||||
|
|
|
@ -1,6 +1,9 @@
|
|||
|
||||
include $(top_srcdir)/aminclude_static.am
|
||||
|
||||
TESTS_ENVIRONMENT = $(SHELL) $(top_builddir)/TESTS_ENVIRONMENT
|
||||
LOG_COMPILER = $(SHELL) $(top_builddir)/TESTS_ENVIRONMENT
|
||||
|
||||
BUILT_SOURCES = tailerbin.h tailerbin.cc
|
||||
|
||||
AM_CPPFLAGS = \
|
||||
|
@ -58,7 +61,7 @@ libtailerservice_a_SOURCES = \
|
|||
tailerbin.cc \
|
||||
tailer.looper.cc
|
||||
|
||||
noinst_PROGRAMS = \
|
||||
check_PROGRAMS = \
|
||||
drive_tailer \
|
||||
tailer
|
||||
|
||||
|
@ -80,6 +83,12 @@ drive_tailer_LDADD = \
|
|||
../base/libbase.a \
|
||||
../fmtlib/libcppfmt.a
|
||||
|
||||
dist_noinst_SCRIPTS = \
|
||||
test_tailer.sh
|
||||
|
||||
TESTS = \
|
||||
test_tailer.sh
|
||||
|
||||
DISTCLEANFILES = \
|
||||
tailerbin.h \
|
||||
tailerbin.cc
|
||||
|
|
|
@ -27,21 +27,39 @@
|
|||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <unistd.h>
|
||||
#include "config.h"
|
||||
|
||||
#include <unistd.h>
|
||||
#include <thread>
|
||||
|
||||
#include "ghc/filesystem.hpp"
|
||||
#include "base/auto_pid.hh"
|
||||
#include "auto_fd.hh"
|
||||
#include "tailerpp.hh"
|
||||
#include "line_buffer.hh"
|
||||
|
||||
static void read_err_pipe(auto_fd &err, std::string& eq)
|
||||
{
|
||||
while (true) {
|
||||
char buffer[1024];
|
||||
auto rc = read(err.get(), buffer, sizeof(buffer));
|
||||
|
||||
if (rc <= 0) {
|
||||
break;
|
||||
}
|
||||
|
||||
eq.append(buffer, rc);
|
||||
}
|
||||
}
|
||||
|
||||
int main(int argc, char *const *argv)
|
||||
{
|
||||
auto tmppath = ghc::filesystem::temp_directory_path() / "drive_tailer";
|
||||
auto host = getenv("TAILER_HOST");
|
||||
|
||||
// ghc::filesystem::remove_all(tmppath);
|
||||
ghc::filesystem::create_directories(tmppath);
|
||||
if (argc != 3) {
|
||||
fprintf(stderr,
|
||||
"usage: %s <cmd> <path>\n",
|
||||
argv[0]);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
auto in_pipe_res = auto_pipe::for_child_fd(STDIN_FILENO);
|
||||
if (in_pipe_res.isErr()) {
|
||||
|
@ -59,6 +77,14 @@ int main(int argc, char *const *argv)
|
|||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
auto err_pipe_res = auto_pipe::for_child_fd(STDERR_FILENO);
|
||||
if (err_pipe_res.isErr()) {
|
||||
fprintf(stderr,
|
||||
"cannot open stderr pipe for child: %s\n",
|
||||
out_pipe_res.unwrapErr().c_str());
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
auto fork_res = lnav::pid::from_fork();
|
||||
if (fork_res.isErr()) {
|
||||
fprintf(stderr,
|
||||
|
@ -69,35 +95,52 @@ int main(int argc, char *const *argv)
|
|||
|
||||
auto in_pipe = in_pipe_res.unwrap();
|
||||
auto out_pipe = out_pipe_res.unwrap();
|
||||
auto err_pipe = err_pipe_res.unwrap();
|
||||
auto child = fork_res.unwrap();
|
||||
|
||||
in_pipe.after_fork(child.in());
|
||||
out_pipe.after_fork(child.in());
|
||||
err_pipe.after_fork(child.in());
|
||||
|
||||
if (child.in_child()) {
|
||||
auto this_exe = ghc::filesystem::path(argv[0]);
|
||||
auto exe_dir = this_exe.parent_path();
|
||||
auto tailer_exe = exe_dir / "tailer";
|
||||
char *child_argv[] = { strdup(tailer_exe.c_str()), strdup("-k") };
|
||||
|
||||
if (host != nullptr) {
|
||||
execlp("ssh", "ssh", "-q", host, "./tailer", nullptr);
|
||||
} else {
|
||||
execvp(tailer_exe.c_str(), argv);
|
||||
}
|
||||
execvp(tailer_exe.c_str(), child_argv);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
fprintf(stderr, "info: child pid %d\n", child.in());
|
||||
std::string error_queue;
|
||||
std::thread err_reader([err = std::move(err_pipe.read_end()), &error_queue]() mutable {
|
||||
read_err_pipe(err, error_queue);
|
||||
});
|
||||
|
||||
auto &to_child = in_pipe.write_end();
|
||||
auto &from_child = out_pipe.read_end();
|
||||
auto cmd = std::string(argv[1]);
|
||||
|
||||
for (int lpc = 1; lpc < argc; lpc++) {
|
||||
send_packet(to_child,
|
||||
TPT_OPEN_PATH,
|
||||
TPPT_STRING, argv[lpc],
|
||||
if (cmd == "preview") {
|
||||
send_packet(to_child.get(),
|
||||
TPT_LOAD_PREVIEW,
|
||||
TPPT_STRING, argv[2],
|
||||
TPPT_INT64, int64_t{1234},
|
||||
TPPT_DONE);
|
||||
}
|
||||
else if (cmd == "possible") {
|
||||
send_packet(to_child.get(),
|
||||
TPT_COMPLETE_PATH,
|
||||
TPPT_STRING, argv[2],
|
||||
TPPT_DONE);
|
||||
}
|
||||
else {
|
||||
fprintf(stderr,
|
||||
"error: unknown command -- %s\n", cmd.c_str());
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
close(to_child.get());
|
||||
|
||||
bool done = false;
|
||||
while (!done) {
|
||||
|
@ -123,10 +166,8 @@ int main(int argc, char *const *argv)
|
|||
|
||||
auto remote_path = ghc::filesystem::absolute(
|
||||
ghc::filesystem::path(pe.pe_path)).relative_path();
|
||||
auto local_path = tmppath / remote_path;
|
||||
|
||||
printf("removing %s\n", local_path.c_str());
|
||||
ghc::filesystem::remove_all(local_path);
|
||||
printf("removing %s\n", remote_path.c_str());
|
||||
},
|
||||
[&](const tailer::packet_offer_block &pob) {
|
||||
printf("Got an offer: %s %lld - %lld\n", pob.pob_path.c_str(),
|
||||
|
@ -134,6 +175,7 @@ int main(int argc, char *const *argv)
|
|||
|
||||
auto remote_path = ghc::filesystem::absolute(
|
||||
ghc::filesystem::path(pob.pob_path)).relative_path();
|
||||
#if 0
|
||||
auto local_path = tmppath / remote_path;
|
||||
auto fd = auto_fd(open(local_path.c_str(), O_RDONLY));
|
||||
|
||||
|
@ -181,8 +223,10 @@ int main(int argc, char *const *argv)
|
|||
TPT_NEED_BLOCK,
|
||||
TPPT_STRING, pob.pob_path.c_str(),
|
||||
TPPT_DONE);
|
||||
#endif
|
||||
},
|
||||
[&](const tailer::packet_tail_block &ptb) {
|
||||
#if 0
|
||||
//printf("got a tail: %s %lld %ld\n", ptb.ptb_path.c_str(),
|
||||
// ptb.ptb_offset, ptb.ptb_bits.size());
|
||||
auto remote_path = ghc::filesystem::absolute(
|
||||
|
@ -200,6 +244,7 @@ int main(int argc, char *const *argv)
|
|||
ftruncate(fd, ptb.ptb_offset);
|
||||
pwrite(fd, ptb.ptb_bits.data(), ptb.ptb_bits.size(), ptb.ptb_offset);
|
||||
}
|
||||
#endif
|
||||
},
|
||||
[&](const tailer::packet_synced &ps) {
|
||||
|
||||
|
@ -208,13 +253,19 @@ int main(int argc, char *const *argv)
|
|||
|
||||
},
|
||||
[&](const tailer::packet_preview_error &ppe) {
|
||||
|
||||
fprintf(stderr,
|
||||
"preview error: %s -- %s\n",
|
||||
ppe.ppe_path.c_str(),
|
||||
ppe.ppe_msg.c_str());
|
||||
},
|
||||
[&](const tailer::packet_preview_data &ppd) {
|
||||
|
||||
printf("preview of file: %s\n%.*s\n",
|
||||
ppd.ppd_path.c_str(),
|
||||
(int) ppd.ppd_bits.size(),
|
||||
ppd.ppd_bits.data());
|
||||
},
|
||||
[&](const tailer::packet_possible_path &ppp) {
|
||||
|
||||
printf("possible path: %s\n", ppp.ppp_path.c_str());
|
||||
}
|
||||
);
|
||||
}
|
||||
|
@ -223,4 +274,9 @@ int main(int argc, char *const *argv)
|
|||
if (!finished_child.was_normal_exit()) {
|
||||
fprintf(stderr, "error: child exited abnormally\n");
|
||||
}
|
||||
|
||||
err_reader.join();
|
||||
|
||||
printf("tailer stderr:\n%s", error_queue.c_str());
|
||||
fprintf(stderr, "tailer stderr:\n%s", error_queue.c_str());
|
||||
}
|
||||
|
|
|
@ -848,7 +848,9 @@ int main(int argc, char *argv[])
|
|||
recv_state_t rstate = RS_PACKET_TYPE;
|
||||
|
||||
// No need to leave ourselves around
|
||||
unlink(argv[0]);
|
||||
if (argc == 1) {
|
||||
unlink(argv[0]);
|
||||
}
|
||||
|
||||
list_init(&client_path_list);
|
||||
|
||||
|
|
|
@ -0,0 +1,36 @@
|
|||
#!/bin/bash
|
||||
|
||||
run_test ./drive_tailer preview nonexistent-file
|
||||
|
||||
check_error_output "preview of nonexistent-file failed?" <<EOF
|
||||
preview error: nonexistent-file -- error: cannot open nonexistent-file -- No such file or directory
|
||||
tailer stderr:
|
||||
info: load preview request -- 1234
|
||||
info: exiting...
|
||||
EOF
|
||||
|
||||
run_test ./drive_tailer preview ${test_dir}/logfile_access_log.0
|
||||
|
||||
check_output "preview of file failed?" <<EOF
|
||||
preview of file: {test_dir}/logfile_access_log.0
|
||||
192.168.202.254 - - [20/Jul/2009:22:59:26 +0000] "GET /vmw/cgi/tramp HTTP/1.0" 200 134 "-" "gPXE/0.9.7"
|
||||
192.168.202.254 - - [20/Jul/2009:22:59:29 +0000] "GET /vmw/vSphere/default/vmkboot.gz HTTP/1.0" 404 46210 "-" "gPXE/0.9.7"
|
||||
192.168.202.254 - - [20/Jul/2009:22:59:29 +0000] "GET /vmw/vSphere/default/vmkernel.gz HTTP/1.0" 200 78929 "-" "gPXE/0.9.7"
|
||||
|
||||
all done!
|
||||
tailer stderr:
|
||||
info: load preview request -- 1234
|
||||
info: exiting...
|
||||
EOF
|
||||
|
||||
run_test ./drive_tailer possible "${test_dir}/logfile_access_log.*"
|
||||
|
||||
check_output "possible path list failed?" <<EOF
|
||||
possible path: {test_dir}/logfile_access_log.0
|
||||
possible path: {test_dir}/logfile_access_log.1
|
||||
all done!
|
||||
tailer stderr:
|
||||
complete path: {test_dir}/logfile_access_log.*
|
||||
complete glob path: {test_dir}/logfile_access_log.*
|
||||
info: exiting...
|
||||
EOF
|
|
@ -1096,9 +1096,9 @@ check_output "multiline commands do not work?" <<EOF
|
|||
Hello: Jules
|
||||
EOF
|
||||
|
||||
|
||||
printf 'Hello, World!' | run_test ${lnav_test} -n \
|
||||
printf "Hello, World!" | run_test ${lnav_test} -n \
|
||||
-c ":switch-to-view text"
|
||||
test_num=`expr ${test_num} \+ 1`
|
||||
|
||||
check_output "stdin with no line feed failed" <<EOF
|
||||
Hello, World!
|
||||
|
|
|
@ -45,10 +45,8 @@ run_test ${lnav_test} -n \
|
|||
-I ${test_dir}/bad-config2 \
|
||||
${test_dir}/logfile_access_log.0
|
||||
|
||||
sed -i "" -e "s|/.*/format|format|g" `test_err_filename`
|
||||
|
||||
check_error_output "config bad theme" <<EOF
|
||||
warning:formats/invalid-config/config.malformed.json:line 2
|
||||
warning:{test_dir}/bad-config2/formats/invalid-config/config.malformed.json:line 2
|
||||
warning: unexpected path --
|
||||
warning: /ui
|
||||
warning: accepted paths --
|
||||
|
@ -56,7 +54,7 @@ warning: \$schema The URI of the schema for this file -- Specifies the type o
|
|||
warning: tuning -- Internal settings
|
||||
warning: ui -- User-interface settings
|
||||
warning: global -- Global variable definitions
|
||||
warning:formats/invalid-config/config.truncated.json:line 2
|
||||
warning:{test_dir}/bad-config2/formats/invalid-config/config.truncated.json:line 2
|
||||
warning: unexpected path --
|
||||
warning: /ui
|
||||
warning: accepted paths --
|
||||
|
@ -64,8 +62,8 @@ warning: \$schema The URI of the schema for this file -- Specifies the type o
|
|||
warning: tuning -- Internal settings
|
||||
warning: ui -- User-interface settings
|
||||
warning: global -- Global variable definitions
|
||||
error:formats/invalid-config/config.malformed.json:3:invalid json -- parse error: object key and value must be separated by a colon (':')
|
||||
error:{test_dir}/bad-config2/formats/invalid-config/config.malformed.json:3:invalid json -- parse error: object key and value must be separated by a colon (':')
|
||||
"ui": "theme", "abc", "def": "" }
|
||||
(right here) ------^
|
||||
error:formats/invalid-config/config.truncated.json: invalid json -- parse error: premature EOF
|
||||
error:{test_dir}/bad-config2/formats/invalid-config/config.truncated.json: invalid json -- parse error: premature EOF
|
||||
EOF
|
||||
|
|
|
@ -6,10 +6,8 @@ lnav_test="${top_builddir}/src/lnav-test"
|
|||
run_test ${lnav_test} -C \
|
||||
-I ${test_dir}/bad-config-json
|
||||
|
||||
sed -i "" -e "s|/.*/format|format|g" `test_err_filename`
|
||||
|
||||
check_error_output "invalid format not detected?" <<EOF
|
||||
warning:format.json:line 5
|
||||
warning:{test_dir}/bad-config-json/formats/invalid-key/format.json:line 5
|
||||
warning: unexpected path --
|
||||
warning: /invalid_key_log/value/test/identifiers
|
||||
warning: accepted paths --
|
||||
|
@ -22,7 +20,7 @@ warning: hidden <bool> -- Indicates whether or not this field should be hidde
|
|||
warning: action-list <string> -- Actions to execute when this field is clicked on
|
||||
warning: rewriter <command> -- A command that will rewrite this field when pretty-printing
|
||||
warning: description <string> -- A description of the field
|
||||
error:format.json:4:invalid json -- parse error: object key and value must be separated by a colon (':')
|
||||
error:{test_dir}/bad-config-json/formats/invalid-json/format.json:4:invalid json -- parse error: object key and value must be separated by a colon (':')
|
||||
ar_log": { "abc" } }
|
||||
(right here) ------^
|
||||
error:foobar_log: no regexes specified for format
|
||||
|
@ -34,12 +32,8 @@ EOF
|
|||
run_test ${lnav_test} -C \
|
||||
-I ${test_dir}/bad-config
|
||||
|
||||
sed -i "" -e "s|/.*/init.sql|init.sql|g" \
|
||||
-e "s|/.*/format|format|g" \
|
||||
`test_err_filename`
|
||||
|
||||
check_error_output "invalid format not detected?" <<EOF
|
||||
error:format.json:line 18
|
||||
error:{test_dir}/bad-config/formats/invalid-sample/format.json:line 18
|
||||
Invalid value, 'foo', for option:
|
||||
/bad_sample_log/value/pid/kind string|integer|float|boolean|json|quoted -- The type of data in the field
|
||||
Allowed values:
|
||||
|
@ -65,7 +59,7 @@ error: against pattern bad_sample_log/regex/semi -- ^(?<timestamp>\d+); (?<body
|
|||
error:bad_sample_log:partial sample matched -- 1428634687123
|
||||
error: against pattern bad_sample_log/regex/std -- ^(?<timestamp>\d+): (?<pid>\w+) (?<body>.*)$
|
||||
error:no_sample_log:no sample logs provided, all formats must have samples
|
||||
error:init.sql:2:near "TALE": syntax error
|
||||
error:{test_dir}/bad-config/formats/invalid-sql/init.sql:2:near "TALE": syntax error
|
||||
EOF
|
||||
|
||||
run_test ${lnav_test} -n \
|
||||
|
|
|
@ -488,15 +488,16 @@ info 0x0
|
|||
error 0x0
|
||||
EOF
|
||||
|
||||
|
||||
echo "Hi" | run_test ${lnav_test} -d /tmp/lnav.err -nt -w logfile_stdin.log
|
||||
run_test ${lnav_test} -d /tmp/lnav.err -nt -w logfile_stdin.log <<EOF
|
||||
Hi
|
||||
EOF
|
||||
|
||||
check_output "piping to stdin is not working?" <<EOF
|
||||
2013-06-06T19:13:20.123 Hi
|
||||
2013-06-06T19:13:20.123 ---- END-OF-STDIN ----
|
||||
EOF
|
||||
|
||||
run_test ${lnav_test} -C ${srcdir}/logfile_bad_access_log.0
|
||||
run_test ${lnav_test} -C ${test_dir}/logfile_bad_access_log.0
|
||||
|
||||
sed -i "" -e "s|/.*/logfile_bad_access_log.0|logfile_bad_access_log.0|g" `test_err_filename`
|
||||
|
||||
|
|
|
@ -25,8 +25,9 @@ Mar 24 15:17:38.999 000000000264F I shmem.res 262144 262144 1 chassis_msg_svc/o
|
|||
)::{lambda()#1}>, osenv::req>->fiber stacks
|
||||
EOF
|
||||
|
||||
echo '2015-04-18T13:16:30.003 8.8.8.8 <foo>8.8.8.8</foo>9 8.8.8.8<1054 198.51.100.1546 544.9.8.7 98.542.241.99 19143.2.5.6' | \
|
||||
run_test ${lnav_test} -n -c ":switch-to-view pretty"
|
||||
run_test ${lnav_test} -n -c ":switch-to-view pretty" <<EOF
|
||||
2015-04-18T13:16:30.003 8.8.8.8 <foo>8.8.8.8</foo>9 8.8.8.8<1054 198.51.100.1546 544.9.8.7 98.542.241.99 19143.2.5.6
|
||||
EOF
|
||||
|
||||
check_output "pretty print not able to properly grok ipv4?" <<EOF
|
||||
2015-04-18T13:16:30.003 8.8.8.8
|
||||
|
|
|
@ -213,9 +213,11 @@ check_error_output "rename-stdin when there is no stdin file?" <<EOF
|
|||
../test/.lnav/formats/default/rename-stdin.lnav:7: error: no data was redirected to lnav's standard-input
|
||||
EOF
|
||||
|
||||
echo 'Hello, World!' | run_test ${lnav_test} -n \
|
||||
run_test ${lnav_test} -n \
|
||||
-c "|rename-stdin foo" \
|
||||
-c ";SELECT filepath FROM lnav_file"
|
||||
-c ";SELECT filepath FROM lnav_file" <<EOF
|
||||
Hello, World!
|
||||
EOF
|
||||
|
||||
check_output "rename of stdin did not work?" <<EOF
|
||||
filepath
|
||||
|
@ -1246,8 +1248,9 @@ llline,jgline
|
|||
EOF
|
||||
|
||||
|
||||
cat ${test_dir}/logfile_syslog.0 | run_test ${lnav_test} -n \
|
||||
-c ";select log_body from syslog_log where log_procname = 'automount'"
|
||||
run_test ${lnav_test} -n \
|
||||
-c ";select log_body from syslog_log where log_procname = 'automount'" \
|
||||
< ${test_dir}/logfile_syslog.0
|
||||
|
||||
check_output "querying against stdin is not working?" <<EOF
|
||||
log_body
|
||||
|
@ -1257,8 +1260,9 @@ check_output "querying against stdin is not working?" <<EOF
|
|||
EOF
|
||||
|
||||
|
||||
cat ${test_dir}/logfile_syslog.0 | run_test ${lnav_test} -n \
|
||||
-c ";select log_body from syslog_log where log_procname = 'sudo'"
|
||||
run_test ${lnav_test} -n \
|
||||
-c ";select log_body from syslog_log where log_procname = 'sudo'" \
|
||||
< ${test_dir}/logfile_syslog.0
|
||||
|
||||
check_output "single result is not working?" <<EOF
|
||||
log_body
|
||||
|
|
Loading…
Reference in New Issue