diff --git a/Makefile.in b/Makefile.in index 2b83c85a..ee75e119 100644 --- a/Makefile.in +++ b/Makefile.in @@ -157,7 +157,7 @@ test/gmock-main.o: $(GMOCK_DIR)/src/gmock_main.cc Makefile test/Integration.o: test/Integration.cpp Makefile @mkdir -p .depend test $(E) Building test object Integration... - $(Q)g++ $(qt_CFLAGS) $(GTEST_FLAGS) -c -o $@ $< -MD -MF .depend/Integration.test.dep -MT $@ '-DZNC_BIN_DIR="$(bindir)"' + $(Q)g++ $(qt_CFLAGS) $(GTEST_FLAGS) -c -o $@ $< -MD -MF .depend/Integration.test.dep -MT $@ '-DZNC_BIN_DIR="$(bindir)"' '-DZNC_SRC_DIR="$(realpath $(srcdir))"' test/Int-gtest-all.o: $(GTEST_DIR)/src/gtest-all.cc Makefile @mkdir -p .depend test $(E) Building test object Int-gtest-all... diff --git a/test/Integration.cpp b/test/Integration.cpp index 4b095ed4..b7a37ba6 100644 --- a/test/Integration.cpp +++ b/test/Integration.cpp @@ -45,6 +45,10 @@ #define ZNC_BIN_DIR "" #endif +#ifndef ZNC_SRC_DIR +#define ZNC_SRC_DIR "" +#endif + using testing::AnyOf; using testing::Eq; using testing::HasSubstr; @@ -126,11 +130,9 @@ using Socket = IO; class Process : public IO { public: - Process(QString cmd, QStringList args, bool interactive) + Process(QString cmd, QStringList args, + std::function setup = [](QProcess*) {}) : IO(&m_proc, true) { - if (!interactive) { - m_proc.setProcessChannelMode(QProcess::ForwardedChannels); - } auto env = QProcessEnvironment::systemEnvironment(); // Default exit codes of sanitizers upon error: // ASAN - 1 @@ -142,6 +144,7 @@ class Process : public IO { // error. env.insert("ASAN_OPTIONS", "exitcode=57"); m_proc.setProcessEnvironment(env); + setup(&m_proc); m_proc.start(cmd, args); } ~Process() override { @@ -179,8 +182,7 @@ void WriteConfig(QString path) { // clang-format off Process p(ZNC_BIN_DIR "/znc", QStringList() << "--debug" << "--datadir" << path - << "--makeconf", - true); + << "--makeconf"); p.ReadUntil("Listen on port");Z; p.Write("12345"); p.ReadUntil("Listen using SSL");Z; p.Write(); p.ReadUntil("IPv6");Z; p.Write(); @@ -210,8 +212,7 @@ TEST(Config, AlreadyExists) { Z; Process p(ZNC_BIN_DIR "/znc", QStringList() << "--debug" << "--datadir" << dir.path() - << "--makeconf", - true); + << "--makeconf"); p.ReadUntil("already exists"); Z; p.CanDie(); @@ -261,7 +262,9 @@ class ZNCTest : public testing::Test { return std::unique_ptr( new Process("./znc", QStringList() << "--debug" << "--datadir" << m_dir.path(), - false)); + [](QProcess* proc) { + proc->setProcessChannelMode(QProcess::ForwardedChannels); + })); } Socket LoginClient() { @@ -1810,4 +1813,38 @@ TEST_F(ZNCTest, Encoding) { Z; } +TEST_F(ZNCTest, BuildMod) { + auto znc = Run(); + Z; + auto ircd = ConnectIRCd(); + Z; + auto client = LoginClient(); + Z; + QDir dir(m_dir.path()); + EXPECT_TRUE(dir.mkdir("modules")); + EXPECT_TRUE(dir.cd("modules")); + { + Process p(ZNC_BIN_DIR "/znc-buildmod", + QStringList() << ZNC_SRC_DIR "/test/file-not-found.cpp", + [&](QProcess* proc) { + proc->setWorkingDirectory(dir.absolutePath()); + proc->setProcessChannelMode(QProcess::ForwardedChannels); + }); + p.ShouldFinishItself(1); + } + { + Process p(ZNC_BIN_DIR "/znc-buildmod", + QStringList() << ZNC_SRC_DIR "/test/testmod.cpp", + [&](QProcess* proc) { + proc->setWorkingDirectory(dir.absolutePath()); + proc->setProcessChannelMode(QProcess::ForwardedChannels); + }); + p.ShouldFinishItself(); + } + client.Write("znc loadmod testmod"); + client.Write("PRIVMSG *testmod :hi"); + client.ReadUntil("Lorem ipsum"); + Z; +} + } // namespace diff --git a/test/testmod.cpp b/test/testmod.cpp new file mode 100644 index 00000000..3cb4f1cb --- /dev/null +++ b/test/testmod.cpp @@ -0,0 +1,27 @@ +/* + * Copyright (C) 2004-2016 ZNC, see the NOTICE file for details. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * 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. + */ + +#include + +class TestModule : public CModule { + public: + MODCONSTRUCTOR(TestModule) {} + void OnModCommand(const CString& sLine) override { + PutModule("Lorem ipsum"); + } +}; + +MODULEDEFS(TestModule, "Test")