/*
* Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*
*/
#include "precompiled.hpp"
#include "logging/logDecorators.hpp"
#include "unittest.hpp"
static LogDecorators::Decorator decorator_array[] = {
#define DECORATOR(name, abbr) LogDecorators::name##_decorator,
DECORATOR_LIST
#undef DECORATOR
};
static const char* decorator_name_array[] = {
#define DECORATOR(name, abbr) #name,
DECORATOR_LIST
#undef DECORATOR
};
static const char* decorator_abbr_array[] = {
#define DECORATOR(name, abbr) #abbr,
DECORATOR_LIST
#undef DECORATOR
};
// Assert that the given decorators object has the default decorators (uptime, level, tags)
// If exclusive = true, also assert that no other decorators are selected
static void assert_default_decorators(LogDecorators* decorators, bool exclusive = true) {
for (int i = 0; i < LogDecorators::Count; i++) {
LogDecorators::Decorator decorator = decorator_array[i];
if (decorator == LogDecorators::uptime_decorator ||
decorator == LogDecorators::level_decorator ||
decorator == LogDecorators::tags_decorator) {
EXPECT_TRUE(decorators->is_decorator(decorator));
} else if (exclusive) {
EXPECT_FALSE(decorators->is_decorator(decorator));
}
}
}
TEST(LogDecorators, defaults) {
LogDecorators decorators;
assert_default_decorators(&decorators);
}
// Test converting between name and decorator (string and enum)
TEST(LogDecorators, from_and_to_name) {
EXPECT_EQ(LogDecorators::Invalid, LogDecorators::from_string("unknown"));
EXPECT_EQ(LogDecorators::Invalid, LogDecorators::from_string(""));
for (int i = 0; i < LogDecorators::Count; i++) {
LogDecorators::Decorator decorator = decorator_array[i];
const char* name = LogDecorators::name(decorator);
EXPECT_STREQ(decorator_name_array[i], name);
LogDecorators::Decorator decorator2 = LogDecorators::from_string(name);
EXPECT_EQ(decorator, decorator2);
// Test case insensitivity
char* name_cpy = strdup(name);
name_cpy[0] = toupper(name_cpy[0]);
decorator2 = LogDecorators::from_string(name_cpy);
free(name_cpy);
EXPECT_EQ(decorator, decorator2);
}
}
// Test decorator abbreviations
TEST(LogDecorators, from_and_to_abbr) {
for (int i = 0; i < LogDecorators::Count; i++) {
LogDecorators::Decorator decorator = decorator_array[i];
const char* abbr = LogDecorators::abbreviation(decorator);
EXPECT_STREQ(decorator_abbr_array[i], abbr);
LogDecorators::Decorator decorator2 = LogDecorators::from_string(abbr);
ASSERT_EQ(decorator, decorator2);
// Test case insensitivity
char* abbr_cpy = strdup(abbr);
abbr_cpy[0] = toupper(abbr_cpy[0]);
decorator2 = LogDecorators::from_string(abbr_cpy);
free(abbr_cpy);
EXPECT_EQ(decorator, decorator2);
}
}
TEST(LogDecorators, parse_default) {
LogDecorators decorators;
decorators.parse(""); // Empty string means we should use the default decorators
assert_default_decorators(&decorators);
}
// Test that "none" gives no decorators at all
TEST(LogDecorators, parse_none) {
LogDecorators decorators;
decorators.parse("none");
for (int i = 0; i < LogDecorators::Count; i++) {
EXPECT_FALSE(decorators.is_decorator(decorator_array[i]));
}
}
// Test a few invalid decorator selections
TEST(LogDecorators, parse_invalid) {
LogDecorators decorators;
EXPECT_FALSE(decorators.parse("invalid"));
EXPECT_FALSE(decorators.parse(",invalid"));
EXPECT_FALSE(decorators.parse(",invalid,"));
assert_default_decorators(&decorators);
}
// Assert that the given decorator has all decorators between first and last
static void assert_decorations_between(const LogDecorators* decorator, size_t first, size_t last) {
for (size_t i = 0; i < ARRAY_SIZE(decorator_array); i++) {
if (i >= first && i <= last) {
EXPECT_TRUE(decorator->is_decorator(decorator_array[i]));
} else {
EXPECT_FALSE(decorator->is_decorator(decorator_array[i]));
}
}
}
TEST(LogDecorators, parse) {
LogDecorators decorators;
// Verify a bunch of different decorator selections
char decstr[1 * K];
decstr[0] = '\0';
size_t written = 0;
for (size_t i = 0; i < ARRAY_SIZE(decorator_array); i++) {
for (size_t j = i; j < ARRAY_SIZE(decorator_array); j++) {
for (size_t k = i; k <= j; k++) {
ASSERT_LT(written, sizeof(decstr)) << "decstr overflow";
int ret = jio_snprintf(decstr + written, sizeof(decstr) - written, "%s%s",
written == 0 ? "" : ",",
((k + j) % 2 == 0) ? decorator_name_array[k] : decorator_abbr_array[k]);
ASSERT_NE(-1, ret);
written += ret;
}
EXPECT_TRUE(decorators.parse(decstr)) << "Valid decorator selection did not parse: " << decstr;
assert_decorations_between(&decorators, i, j);
written = 0;
decstr[0] = '\0';
}
}
}
TEST(LogDecorators, combine_with) {
LogDecorators dec1;
LogDecorators dec2;
// Select first and third decorator for dec1
char input[64];
sprintf(input, "%s,%s", decorator_name_array[0], decorator_name_array[2]);
dec1.parse(input);
EXPECT_TRUE(dec1.is_decorator(decorator_array[0]));
EXPECT_TRUE(dec1.is_decorator(decorator_array[2]));
// Select the default decorators for dec2
EXPECT_FALSE(dec2.is_decorator(decorator_array[0]));
EXPECT_FALSE(dec2.is_decorator(decorator_array[2]));
assert_default_decorators(&dec2);
// Combine and verify that the combination includes first, third and default decorators
dec2.combine_with(dec1);
EXPECT_TRUE(dec2.is_decorator(decorator_array[0]));
EXPECT_TRUE(dec2.is_decorator(decorator_array[2]));
assert_default_decorators(&dec2, false);
}
TEST(LogDecorators, clear) {
// Start with default decorators and then clear it
LogDecorators dec;
EXPECT_FALSE(dec.is_empty());
dec.clear();
EXPECT_TRUE(dec.is_empty());
for (size_t i = 0; i < LogDecorators::Count; i++) {
EXPECT_FALSE(dec.is_decorator(decorator_array[i]));
}
}
// Test the decorator constant None
TEST(LogDecorators, none) {
LogDecorators dec = LogDecorators::None;
for (size_t i = 0; i < LogDecorators::Count; i++) {
EXPECT_FALSE(dec.is_decorator(decorator_array[i]));
}
}
TEST(LogDecorators, is_empty) {
LogDecorators def, none = LogDecorators::None;
EXPECT_FALSE(def.is_empty());
EXPECT_TRUE(none.is_empty());
}