adamdebreceni commented on a change in pull request #976:
URL: https://github.com/apache/nifi-minifi-cpp/pull/976#discussion_r559359639



##########
File path: extensions/windows-event-log/tests/ConsumeWindowsEventLogTests.cpp
##########
@@ -300,53 +330,249 @@ TEST_CASE("ConsumeWindowsEventLog output format can be 
set", "[create][output_fo
   outputFormatSetterTestHelper("InvalidValue", 0);
 }
 
+namespace {
+
+class OutputFormatTestController : public TestController {
+ public:
+  OutputFormatTestController(std::string channel, std::string query, 
std::string output_format)
+    : channel_(std::move(channel)),
+      query_(std::move(query)),
+      output_format_(std::move(output_format)) {}
+
+  std::string run() {
+    LogTestController::getInstance().setDebug<ConsumeWindowsEventLog>();
+    LogTestController::getInstance().setDebug<LogAttribute>();
+    std::shared_ptr<TestPlan> test_plan = createPlan();
+
+    auto cwel_processor = test_plan->addProcessor("ConsumeWindowsEventLog", 
"cwel");
+    test_plan->setProperty(cwel_processor, 
ConsumeWindowsEventLog::Channel.getName(), channel_);
+    test_plan->setProperty(cwel_processor, 
ConsumeWindowsEventLog::Query.getName(), query_);
+    test_plan->setProperty(cwel_processor, 
ConsumeWindowsEventLog::OutputFormat.getName(), output_format_);
+
+    auto dir = utils::createTempDir(this);
+
+    auto put_file = test_plan->addProcessor("PutFile", "putFile", Success, 
true);
+    test_plan->setProperty(put_file, PutFile::Directory.getName(), dir);
+
+    {
+      dispatchBookmarkEvent();
+
+      runSession(test_plan);
+    }
+
+    test_plan->reset();
+    
LogTestController::getInstance().resetStream(LogTestController::getInstance().log_output);
+
+
+    {
+      dispatchCollectedEvent();
+
+      runSession(test_plan);
+
+      auto files = utils::file::list_dir_all(dir, 
LogTestController::getInstance().getLogger<LogTestController>(), false);
+      REQUIRE(files.size() == 1);
+
+      std::ifstream file{utils::file::concat_path(files[0].first, 
files[0].second)};
+      return {std::istreambuf_iterator<char>{file}, {}};
+    }
+  }
+
+ protected:
+  virtual void dispatchBookmarkEvent() = 0;
+  virtual void dispatchCollectedEvent() = 0;
+
+  std::string channel_;
+  std::string query_;
+  std::string output_format_;
+};
+
+}  // namespace
+
 // NOTE(fgerlits): I don't know how to unit test this, as my manually 
published events all result in an empty string if OutputFormat is Plaintext
 //                 but it does seem to work, based on manual tests reading 
system logs
 // TEST_CASE("ConsumeWindowsEventLog prints events in plain text correctly", 
"[onTrigger]")
 
 TEST_CASE("ConsumeWindowsEventLog prints events in XML correctly", 
"[onTrigger]") {
-  TestController test_controller;
-  LogTestController::getInstance().setDebug<ConsumeWindowsEventLog>();
-  LogTestController::getInstance().setDebug<LogAttribute>();
-  std::shared_ptr<TestPlan> test_plan = test_controller.createPlan();
+  class XMLFormat : public OutputFormatTestController {
+   public:
+    XMLFormat() : OutputFormatTestController(APPLICATION_CHANNEL, QUERY, 
"XML") {}
 
-  auto cwel_processor = test_plan->addProcessor("ConsumeWindowsEventLog", 
"cwel");
-  test_plan->setProperty(cwel_processor, 
ConsumeWindowsEventLog::Channel.getName(), APPLICATION_CHANNEL);
-  test_plan->setProperty(cwel_processor, 
ConsumeWindowsEventLog::Query.getName(), QUERY);
-  test_plan->setProperty(cwel_processor, 
ConsumeWindowsEventLog::OutputFormat.getName(), "XML");
+   protected:
+    void dispatchBookmarkEvent() override {
+      reportEvent(APPLICATION_CHANNEL, "Event zero: this is in the past");
+    }
+    void dispatchCollectedEvent() override {
+      reportEvent(APPLICATION_CHANNEL, "Event one");
+    }
+  } test_controller;
+
+  std::string event = test_controller.run();
+
+  REQUIRE(event.find(R"(<Event 
xmlns="http://schemas.microsoft.com/win/2004/08/events/event";><System><Provider 
Name="Application"/>)") != std::string::npos);
+  REQUIRE(event.find(R"(<EventID Qualifiers="0">14985</EventID>)") != 
std::string::npos);
+  REQUIRE(event.find(R"(<Level>4</Level>)") != std::string::npos);
+  REQUIRE(event.find(R"(<Task>0</Task>)") != std::string::npos);
+  REQUIRE(event.find(R"(<Keywords>0x80000000000000</Keywords><TimeCreated 
SystemTime=")") != std::string::npos);
+  // the timestamp (when the event was published) goes here
+  REQUIRE(event.find(R"("/><EventRecordID>)") != std::string::npos);
+  // the ID of the event goes here (a number)
+  REQUIRE(event.find(R"(</EventRecordID>)") != std::string::npos);
+  REQUIRE(event.find(R"(<Channel>Application</Channel><Computer>)") != 
std::string::npos);
+  // the computer name goes here
+  REQUIRE(event.find(R"(</Computer><Security/></System><EventData><Data>Event 
one</Data></EventData></Event>)") != std::string::npos);
+}
 
-  auto logger_processor = test_plan->addProcessor("LogAttribute", "logger", 
Success, true);
-  test_plan->setProperty(logger_processor, 
LogAttribute::FlowFilesToLog.getName(), "0");
-  test_plan->setProperty(logger_processor, LogAttribute::LogPayload.getName(), 
"true");
-  test_plan->setProperty(logger_processor, 
LogAttribute::MaxPayloadLineLength.getName(), "1024");
+namespace {
+// carries out a loose match on objects, i.e. it doesn't matter if the
+// actual object has extra fields than expected
+void matchJSON(const rapidjson::Value& json, const rapidjson::Value& expected) 
{
+  if (expected.IsObject()) {
+    REQUIRE(json.IsObject());
+    for (const auto& expected_member : expected.GetObject()) {
+      REQUIRE(json.HasMember(expected_member.name));
+      matchJSON(json[expected_member.name], expected_member.value);
+    }
+  } else if (expected.IsArray()) {
+    REQUIRE(json.IsArray());
+    REQUIRE(json.Size() == expected.Size());
+    for (size_t idx{0}; idx < expected.Size(); ++idx) {
+      matchJSON(json[idx], expected[idx]);
+    }
+  } else {
+    REQUIRE(json == expected);
+  }
+}
 
-  {
-    reportEvent(APPLICATION_CHANNEL, "Event zero: this is in the past");
+void verifyJSON(const std::string& json_str, const std::string& expected_str) {
+  rapidjson::Document json, expected;
+  REQUIRE(!json.Parse(json_str.c_str()).HasParseError());
+  REQUIRE(!expected.Parse(expected_str.c_str()).HasParseError());
 
-    test_controller.runSession(test_plan);
-  }
+  matchJSON(json, expected);
+}
 
-  test_plan->reset();
-  
LogTestController::getInstance().resetStream(LogTestController::getInstance().log_output);
+class JSONOutputController : public OutputFormatTestController {
+ public:
+  JSONOutputController(std::string format) : 
OutputFormatTestController(APPLICATION_CHANNEL, "*", std::move(format)) {}
 
-  {
+ protected:
+  void dispatchBookmarkEvent() override {
+    reportEvent(APPLICATION_CHANNEL, "Event zero: this is in the past");
+  }
+  void dispatchCollectedEvent() override {
     reportEvent(APPLICATION_CHANNEL, "Event one");
+  }
+};
 
-    test_controller.runSession(test_plan);
+}  // namespace
+
+TEST_CASE("ConsumeWindowsEventLog prints events in JSON::Simple correctly", 
"[onTrigger]") {
+  std::string event = JSONOutputController{"JSON::Simple"}.run();
+  verifyJSON(event, R"json(
+    {
+      "System": {
+        "Provider": {
+          "Name": "Application"
+        },
+        "Channel": "Application"
+      },
+      "EventData": [{
+          "Type": "Data",
+          "Content": "Event one",
+          "Name": ""
+      }]
+    }
+  )json");
+}
+
+TEST_CASE("ConsumeWindowsEventLog prints events in JSON::Raw correctly", 
"[onTrigger]") {
+  std::string event = JSONOutputController{"JSON::Raw"}.run();
+  verifyJSON(event, R"json(
+    [
+      {
+        "name": "Event",
+        "children": [
+          {"name": "System"},
+          {
+            "name": "EventData",
+            "children": [{
+              "name": "Data",
+              "text": "Event one"
+            }] 
+          }      
+        ]
+      }
+    ]
+  )json");
+}
+
+class CustomProviderController : public OutputFormatTestController {
+ public:
+  CustomProviderController(std::string format) : 
OutputFormatTestController(custom_channel, "*", std::move(format)) {}
 
-    REQUIRE(LogTestController::getInstance().contains(R"(<Event 
xmlns="http://schemas.microsoft.com/win/2004/08/events/event";><System><Provider 
Name="Application"/>)"));
-    REQUIRE(LogTestController::getInstance().contains(R"(<EventID 
Qualifiers="0">14985</EventID>)"));
-    REQUIRE(LogTestController::getInstance().contains(R"(<Level>4</Level>)"));
-    REQUIRE(LogTestController::getInstance().contains(R"(<Task>0</Task>)"));
-    
REQUIRE(LogTestController::getInstance().contains(R"(<Keywords>0x80000000000000</Keywords><TimeCreated
 SystemTime=")"));
-    // the timestamp (when the event was published) goes here
-    
REQUIRE(LogTestController::getInstance().contains(R"("/><EventRecordID>)"));
-    // the ID of the event goes here (a number)
-    REQUIRE(LogTestController::getInstance().contains(R"(</EventRecordID>)"));
-    
REQUIRE(LogTestController::getInstance().contains(R"(<Channel>Application</Channel><Computer>)"));
-    // the computer name goes here
-    
REQUIRE(LogTestController::getInstance().contains(R"(</Computer><Security/></System><EventData><Data>Event
 one</Data></EventData></Event>)"));
+ protected:
+  void dispatchBookmarkEvent() override {
+    REQUIRE(dispatchCustomEvent({"Bookmark", "Second", "Third", 3, 12}));
+    std::this_thread::sleep_for(std::chrono::seconds{1});

Review comment:
       it is probably due to using powershell to dispatch the event, I hope 
using the API you linked will make it obsolete




----------------------------------------------------------------
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

For queries about this service, please contact Infrastructure at:
[email protected]


Reply via email to