1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim: set ts=2 et sw=2 tw=80: */
3 /* This Source Code Form is subject to the terms of the Mozilla Public
4  * License, v. 2.0. If a copy of the MPL was not distributed with this file,
5  * You can obtain one at http://mozilla.org/MPL/2.0/. */
6 
7 /* Original author: bcampen@mozilla.com */
8 
9 #include "rlogconnector.h"
10 
11 extern "C" {
12 #include "registry.h"
13 #include "r_log.h"
14 }
15 
16 #define GTEST_HAS_RTTI 0
17 #include "gtest/gtest.h"
18 #include "gtest_utils.h"
19 
20 #include <deque>
21 #include <string>
22 #include <vector>
23 
24 using mozilla::RLogConnector;
25 
26 int NR_LOG_TEST = 0;
27 
28 class RLogConnectorTest : public ::testing::Test {
29  public:
RLogConnectorTest()30   RLogConnectorTest() { Init(); }
31 
~RLogConnectorTest()32   ~RLogConnectorTest() { Free(); }
33 
SetUpTestCase()34   static void SetUpTestCase() {
35     NR_reg_init(NR_REG_MODE_LOCAL);
36     r_log_init();
37     /* Would be nice to be able to unregister in the fixture */
38     const char* facility = "rlogconnector_test";
39     r_log_register(const_cast<char*>(facility), &NR_LOG_TEST);
40   }
41 
Init()42   void Init() { RLogConnector::CreateInstance(); }
43 
Free()44   void Free() { RLogConnector::DestroyInstance(); }
45 
ReInit()46   void ReInit() {
47     Free();
48     Init();
49   }
50 };
51 
TEST_F(RLogConnectorTest,TestGetFree)52 TEST_F(RLogConnectorTest, TestGetFree) {
53   RLogConnector* instance = RLogConnector::GetInstance();
54   ASSERT_NE(nullptr, instance);
55 }
56 
TEST_F(RLogConnectorTest,TestFilterEmpty)57 TEST_F(RLogConnectorTest, TestFilterEmpty) {
58   std::deque<std::string> logs;
59   RLogConnector::GetInstance()->GetAny(0, &logs);
60   ASSERT_EQ(0U, logs.size());
61 }
62 
TEST_F(RLogConnectorTest,TestBasicFilter)63 TEST_F(RLogConnectorTest, TestBasicFilter) {
64   r_log(NR_LOG_TEST, LOG_INFO, "Test");
65   std::deque<std::string> logs;
66   RLogConnector::GetInstance()->Filter("Test", 0, &logs);
67   ASSERT_EQ(1U, logs.size());
68 }
69 
TEST_F(RLogConnectorTest,TestBasicFilterContent)70 TEST_F(RLogConnectorTest, TestBasicFilterContent) {
71   r_log(NR_LOG_TEST, LOG_INFO, "Test");
72   std::deque<std::string> logs;
73   RLogConnector::GetInstance()->Filter("Test", 0, &logs);
74   ASSERT_EQ("Test", logs.back());
75 }
76 
TEST_F(RLogConnectorTest,TestFilterAnyFrontMatch)77 TEST_F(RLogConnectorTest, TestFilterAnyFrontMatch) {
78   r_log(NR_LOG_TEST, LOG_INFO, "Test");
79   std::vector<std::string> substrings;
80   substrings.push_back("foo");
81   substrings.push_back("Test");
82   std::deque<std::string> logs;
83   RLogConnector::GetInstance()->FilterAny(substrings, 0, &logs);
84   ASSERT_EQ("Test", logs.back());
85 }
86 
TEST_F(RLogConnectorTest,TestFilterAnyBackMatch)87 TEST_F(RLogConnectorTest, TestFilterAnyBackMatch) {
88   r_log(NR_LOG_TEST, LOG_INFO, "Test");
89   std::vector<std::string> substrings;
90   substrings.push_back("Test");
91   substrings.push_back("foo");
92   std::deque<std::string> logs;
93   RLogConnector::GetInstance()->FilterAny(substrings, 0, &logs);
94   ASSERT_EQ("Test", logs.back());
95 }
96 
TEST_F(RLogConnectorTest,TestFilterAnyBothMatch)97 TEST_F(RLogConnectorTest, TestFilterAnyBothMatch) {
98   r_log(NR_LOG_TEST, LOG_INFO, "Test");
99   std::vector<std::string> substrings;
100   substrings.push_back("Tes");
101   substrings.push_back("est");
102   std::deque<std::string> logs;
103   RLogConnector::GetInstance()->FilterAny(substrings, 0, &logs);
104   ASSERT_EQ("Test", logs.back());
105 }
106 
TEST_F(RLogConnectorTest,TestFilterAnyNeitherMatch)107 TEST_F(RLogConnectorTest, TestFilterAnyNeitherMatch) {
108   r_log(NR_LOG_TEST, LOG_INFO, "Test");
109   std::vector<std::string> substrings;
110   substrings.push_back("tes");
111   substrings.push_back("esT");
112   std::deque<std::string> logs;
113   RLogConnector::GetInstance()->FilterAny(substrings, 0, &logs);
114   ASSERT_EQ(0U, logs.size());
115 }
116 
TEST_F(RLogConnectorTest,TestAllMatch)117 TEST_F(RLogConnectorTest, TestAllMatch) {
118   r_log(NR_LOG_TEST, LOG_INFO, "Test1");
119   r_log(NR_LOG_TEST, LOG_INFO, "Test2");
120   std::deque<std::string> logs;
121   RLogConnector::GetInstance()->GetAny(0, &logs);
122   ASSERT_EQ(2U, logs.size());
123 }
124 
TEST_F(RLogConnectorTest,TestOrder)125 TEST_F(RLogConnectorTest, TestOrder) {
126   r_log(NR_LOG_TEST, LOG_INFO, "Test1");
127   r_log(NR_LOG_TEST, LOG_INFO, "Test2");
128   std::deque<std::string> logs;
129   RLogConnector::GetInstance()->GetAny(0, &logs);
130   ASSERT_EQ("Test2", logs.back());
131   ASSERT_EQ("Test1", logs.front());
132 }
133 
TEST_F(RLogConnectorTest,TestNoMatch)134 TEST_F(RLogConnectorTest, TestNoMatch) {
135   r_log(NR_LOG_TEST, LOG_INFO, "Test1");
136   r_log(NR_LOG_TEST, LOG_INFO, "Test2");
137   std::deque<std::string> logs;
138   RLogConnector::GetInstance()->Filter("foo", 0, &logs);
139   ASSERT_EQ(0U, logs.size());
140 }
141 
TEST_F(RLogConnectorTest,TestSubstringFilter)142 TEST_F(RLogConnectorTest, TestSubstringFilter) {
143   r_log(NR_LOG_TEST, LOG_INFO, "Test1");
144   r_log(NR_LOG_TEST, LOG_INFO, "Test2");
145   std::deque<std::string> logs;
146   RLogConnector::GetInstance()->Filter("t1", 0, &logs);
147   ASSERT_EQ(1U, logs.size());
148   ASSERT_EQ("Test1", logs.back());
149 }
150 
TEST_F(RLogConnectorTest,TestFilterLimit)151 TEST_F(RLogConnectorTest, TestFilterLimit) {
152   r_log(NR_LOG_TEST, LOG_INFO, "Test1");
153   r_log(NR_LOG_TEST, LOG_INFO, "Test2");
154   r_log(NR_LOG_TEST, LOG_INFO, "Test3");
155   r_log(NR_LOG_TEST, LOG_INFO, "Test4");
156   r_log(NR_LOG_TEST, LOG_INFO, "Test5");
157   r_log(NR_LOG_TEST, LOG_INFO, "Test6");
158   std::deque<std::string> logs;
159   RLogConnector::GetInstance()->Filter("Test", 2, &logs);
160   ASSERT_EQ(2U, logs.size());
161   ASSERT_EQ("Test6", logs.back());
162   ASSERT_EQ("Test5", logs.front());
163 }
164 
TEST_F(RLogConnectorTest,TestFilterAnyLimit)165 TEST_F(RLogConnectorTest, TestFilterAnyLimit) {
166   r_log(NR_LOG_TEST, LOG_INFO, "TestOne");
167   r_log(NR_LOG_TEST, LOG_INFO, "TestTwo");
168   r_log(NR_LOG_TEST, LOG_INFO, "TestThree");
169   r_log(NR_LOG_TEST, LOG_INFO, "TestFour");
170   r_log(NR_LOG_TEST, LOG_INFO, "TestFive");
171   r_log(NR_LOG_TEST, LOG_INFO, "TestSix");
172   std::vector<std::string> substrings;
173   // Matches Two, Three, Four, and Six
174   substrings.push_back("tT");
175   substrings.push_back("o");
176   substrings.push_back("r");
177   substrings.push_back("S");
178   std::deque<std::string> logs;
179   RLogConnector::GetInstance()->FilterAny(substrings, 2, &logs);
180   ASSERT_EQ(2U, logs.size());
181   ASSERT_EQ("TestSix", logs.back());
182   ASSERT_EQ("TestFour", logs.front());
183 }
184 
TEST_F(RLogConnectorTest,TestLimit)185 TEST_F(RLogConnectorTest, TestLimit) {
186   RLogConnector::GetInstance()->SetLogLimit(3);
187   r_log(NR_LOG_TEST, LOG_INFO, "Test1");
188   r_log(NR_LOG_TEST, LOG_INFO, "Test2");
189   r_log(NR_LOG_TEST, LOG_INFO, "Test3");
190   r_log(NR_LOG_TEST, LOG_INFO, "Test4");
191   r_log(NR_LOG_TEST, LOG_INFO, "Test5");
192   r_log(NR_LOG_TEST, LOG_INFO, "Test6");
193   std::deque<std::string> logs;
194   RLogConnector::GetInstance()->GetAny(0, &logs);
195   ASSERT_EQ(3U, logs.size());
196   ASSERT_EQ("Test6", logs.back());
197   ASSERT_EQ("Test4", logs.front());
198 }
199 
TEST_F(RLogConnectorTest,TestLimitBulkDiscard)200 TEST_F(RLogConnectorTest, TestLimitBulkDiscard) {
201   r_log(NR_LOG_TEST, LOG_INFO, "Test1");
202   r_log(NR_LOG_TEST, LOG_INFO, "Test2");
203   r_log(NR_LOG_TEST, LOG_INFO, "Test3");
204   r_log(NR_LOG_TEST, LOG_INFO, "Test4");
205   r_log(NR_LOG_TEST, LOG_INFO, "Test5");
206   r_log(NR_LOG_TEST, LOG_INFO, "Test6");
207   RLogConnector::GetInstance()->SetLogLimit(3);
208   std::deque<std::string> logs;
209   RLogConnector::GetInstance()->GetAny(0, &logs);
210   ASSERT_EQ(3U, logs.size());
211   ASSERT_EQ("Test6", logs.back());
212   ASSERT_EQ("Test4", logs.front());
213 }
214 
TEST_F(RLogConnectorTest,TestIncreaseLimit)215 TEST_F(RLogConnectorTest, TestIncreaseLimit) {
216   RLogConnector::GetInstance()->SetLogLimit(3);
217   r_log(NR_LOG_TEST, LOG_INFO, "Test1");
218   r_log(NR_LOG_TEST, LOG_INFO, "Test2");
219   r_log(NR_LOG_TEST, LOG_INFO, "Test3");
220   r_log(NR_LOG_TEST, LOG_INFO, "Test4");
221   r_log(NR_LOG_TEST, LOG_INFO, "Test5");
222   r_log(NR_LOG_TEST, LOG_INFO, "Test6");
223   RLogConnector::GetInstance()->SetLogLimit(300);
224   std::deque<std::string> logs;
225   RLogConnector::GetInstance()->GetAny(0, &logs);
226   ASSERT_EQ(3U, logs.size());
227   ASSERT_EQ("Test6", logs.back());
228   ASSERT_EQ("Test4", logs.front());
229 }
230 
TEST_F(RLogConnectorTest,TestClear)231 TEST_F(RLogConnectorTest, TestClear) {
232   r_log(NR_LOG_TEST, LOG_INFO, "Test1");
233   r_log(NR_LOG_TEST, LOG_INFO, "Test2");
234   r_log(NR_LOG_TEST, LOG_INFO, "Test3");
235   r_log(NR_LOG_TEST, LOG_INFO, "Test4");
236   r_log(NR_LOG_TEST, LOG_INFO, "Test5");
237   r_log(NR_LOG_TEST, LOG_INFO, "Test6");
238   RLogConnector::GetInstance()->SetLogLimit(0);
239   RLogConnector::GetInstance()->SetLogLimit(4096);
240   std::deque<std::string> logs;
241   RLogConnector::GetInstance()->GetAny(0, &logs);
242   ASSERT_EQ(0U, logs.size());
243 }
244 
TEST_F(RLogConnectorTest,TestReInit)245 TEST_F(RLogConnectorTest, TestReInit) {
246   r_log(NR_LOG_TEST, LOG_INFO, "Test1");
247   r_log(NR_LOG_TEST, LOG_INFO, "Test2");
248   r_log(NR_LOG_TEST, LOG_INFO, "Test3");
249   r_log(NR_LOG_TEST, LOG_INFO, "Test4");
250   r_log(NR_LOG_TEST, LOG_INFO, "Test5");
251   r_log(NR_LOG_TEST, LOG_INFO, "Test6");
252   ReInit();
253   std::deque<std::string> logs;
254   RLogConnector::GetInstance()->GetAny(0, &logs);
255   ASSERT_EQ(0U, logs.size());
256 }
257