| /** |
| * Licensed to the Apache Software Foundation (ASF) under one or more |
| * contributor license agreements. See the NOTICE file distributed with |
| * this work for additional information regarding copyright ownership. |
| * The ASF licenses this file to You 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 "ConsumeWindowsEventLog.h" |
| |
| #include "core/ConfigurableComponent.h" |
| #include "processors/LogAttribute.h" |
| #include "processors/PutFile.h" |
| #include "unit/TestBase.h" |
| #include "unit/Catch.h" |
| #include "unit/TestUtils.h" |
| #include "utils/file/FileUtils.h" |
| #include "wel/UniqueEvtHandle.h" |
| |
| #include "rapidjson/document.h" |
| |
| #include "CWELTestUtils.h" |
| |
| // generated from the manifest file "custom-provider/unit-test-provider.man" |
| // using the command "mc -um unit-test-provider.man" |
| #include "custom-provider/unit-test-provider.h" |
| |
| namespace org::apache::nifi::minifi::test { |
| |
| namespace { |
| |
| struct CustomEventData { |
| std::wstring first; |
| std::wstring second; |
| std::wstring third; |
| int binary_length; |
| const unsigned char* binary_data; |
| }; |
| |
| const std::string CUSTOM_PROVIDER_NAME = "minifi_unit_test_provider"; |
| const std::string CUSTOM_CHANNEL = CUSTOM_PROVIDER_NAME + "/Log"; |
| |
| bool dispatchCustomEvent(const CustomEventData& event) { |
| static auto provider_initialized = EventRegisterminifi_unit_test_provider(); |
| REQUIRE(provider_initialized == ERROR_SUCCESS); |
| |
| auto result = EventWriteCustomEvent( |
| event.first.c_str(), |
| event.second.c_str(), |
| event.third.c_str(), |
| event.binary_length, |
| event.binary_data); |
| return result == ERROR_SUCCESS; |
| } |
| |
| using org::apache::nifi::minifi::wel::unique_evt_handle; |
| |
| bool advanceBookmark(const unique_evt_handle& hBookmark, const std::string& channel, const std::string& query, bool advance_to_last = false) { |
| const auto hEventResults = unique_evt_handle{ EvtQuery(0, std::wstring{channel.begin(), channel.end()}.c_str(), std::wstring{query.begin(), query.end()}.c_str(), EvtQueryChannelPath) }; |
| if (!hEventResults) { |
| return false; |
| } |
| |
| if (advance_to_last) { |
| if (!EvtSeek(hEventResults.get(), 0, 0, 0, EvtSeekRelativeToLast)) { |
| return false; |
| } |
| } else { |
| if (!EvtSeek(hEventResults.get(), 1, hBookmark.get(), 0, EvtSeekRelativeToBookmark)) { |
| return false; |
| } |
| } |
| |
| const unique_evt_handle hEvent = [&hEventResults] { |
| DWORD dwReturned{}; |
| EVT_HANDLE hEvent{ nullptr }; |
| EvtNext(hEventResults.get(), 1, &hEvent, INFINITE, 0, &dwReturned); |
| return unique_evt_handle{ hEvent }; |
| }(); |
| |
| if (!hEvent) { |
| return false; |
| } |
| |
| REQUIRE(EvtUpdateBookmark(hBookmark.get(), hEvent.get())); |
| |
| return true; |
| } |
| |
| class CustomProviderController : public OutputFormatTestController { |
| public: |
| CustomProviderController(std::string format, std::string json_format) : OutputFormatTestController(CUSTOM_CHANNEL, "*", std::move(format), std::move(json_format)) { |
| bookmark_.reset(EvtCreateBookmark(0)); |
| advanceBookmark(bookmark_, channel_, query_, true); |
| REQUIRE(bookmark_); |
| } |
| |
| protected: |
| void dispatchBookmarkEvent() override { |
| auto binary = reinterpret_cast<const unsigned char*>("\x0c\x10"); |
| REQUIRE(dispatchCustomEvent({L"Bookmark", L"Second", L"Third", 2, binary})); |
| REQUIRE(checkNewEventAvailable()); |
| } |
| void dispatchCollectedEvent() override { |
| auto binary = reinterpret_cast<const unsigned char*>("\x09\x01"); |
| REQUIRE(dispatchCustomEvent({L"Actual event", L"Second", L"Third", 2, binary})); |
| REQUIRE(checkNewEventAvailable()); |
| } |
| |
| private: |
| bool checkNewEventAvailable() { |
| return org::apache::nifi::utils::verifyEventHappenedInPollTime(std::chrono::seconds{5}, [&] { |
| return advanceBookmark(bookmark_, channel_, query_); |
| }); |
| } |
| unique_evt_handle bookmark_; |
| }; |
| |
| const std::string EVENT_DATA_JSON = R"( |
| [{ |
| "Type": "Data", |
| "Content": "Actual event", |
| "Name": "param1" |
| }, { |
| "Type": "Data", |
| "Content": "Second", |
| "Name": "param2" |
| }, { |
| "Type": "Data", |
| "Content": "Third", |
| "Name": "Channel" |
| }, { |
| "Type": "Binary", |
| "Content": "0901", |
| "Name": "" |
| }] |
| )"; |
| |
| } // namespace |
| |
| TEST_CASE("ConsumeWindowsEventLog prints events in JSON::Simple correctly custom provider", "[onTrigger]") { |
| std::string event = CustomProviderController{"JSON", "Simple"}.run(); |
| utils::verifyJSON(event, R"( |
| { |
| "System": { |
| "Provider": { |
| "Name": ")" + CUSTOM_PROVIDER_NAME + R"(" |
| }, |
| "Channel": ")" + CUSTOM_CHANNEL + R"(" |
| }, |
| "EventData": )" + EVENT_DATA_JSON + R"( |
| } |
| )"); |
| } |
| |
| TEST_CASE("ConsumeWindowsEventLog prints events in JSON::Flattened correctly custom provider", "[onTrigger]") { |
| std::string event = CustomProviderController{"JSON", "Flattened"}.run(); |
| utils::verifyJSON(event, R"( |
| { |
| "Name": ")" + CUSTOM_PROVIDER_NAME + R"(", |
| "Channel": ")" + CUSTOM_CHANNEL /* Channel is not overwritten by data named "Channel" */ + R"(", |
| "EventData.param1": "Actual event", |
| "EventData.param2": "Second", |
| "EventData.Channel": "Third", |
| "EventData": "0901" |
| } |
| )"); |
| } |
| |
| } // namespace org::apache::nifi::minifi::test |