mirror of https://github.com/Icinga/icinga2.git
parent
f1d37f6aa4
commit
9dfa3d22d4
|
@ -736,6 +736,11 @@ object CheckCommand "nrpe" {
|
|||
description = "Make socket timeouts return an UNKNOWN state instead of CRITICAL"
|
||||
}
|
||||
"-t" = "$nrpe_timeout$"
|
||||
"-a" = {
|
||||
value = "$nrpe_arguments$"
|
||||
repeat_key = false
|
||||
order = 1
|
||||
}
|
||||
}
|
||||
|
||||
vars.nrpe_address = "$address$"
|
||||
|
|
|
@ -212,7 +212,7 @@ String Host::StateTypeToString(StateType type)
|
|||
return "HARD";
|
||||
}
|
||||
|
||||
bool Host::ResolveMacro(const String& macro, const CheckResult::Ptr&, String *result) const
|
||||
bool Host::ResolveMacro(const String& macro, const CheckResult::Ptr&, Value *result) const
|
||||
{
|
||||
if (macro == "state") {
|
||||
*result = StateToString(GetState());
|
||||
|
|
|
@ -63,7 +63,7 @@ public:
|
|||
static StateType StateTypeFromString(const String& state);
|
||||
static String StateTypeToString(StateType state);
|
||||
|
||||
virtual bool ResolveMacro(const String& macro, const CheckResult::Ptr& cr, String *result) const;
|
||||
virtual bool ResolveMacro(const String& macro, const CheckResult::Ptr& cr, Value *result) const;
|
||||
|
||||
protected:
|
||||
virtual void Stop(void);
|
||||
|
|
|
@ -202,10 +202,12 @@
|
|||
%attribute %dictionary "arguments" {
|
||||
%attribute %string "*",
|
||||
%attribute %dictionary "*" {
|
||||
%attribute %string "key"
|
||||
%attribute %string "value"
|
||||
%attribute %string "description"
|
||||
%attribute %number "required"
|
||||
%attribute %number "skip_key"
|
||||
%attribute %number "repeat_key"
|
||||
%attribute %string "set_if"
|
||||
%attribute %number "order"
|
||||
}
|
||||
|
|
|
@ -147,7 +147,7 @@ String IcingaApplication::GetNodeName(void) const
|
|||
return ScriptVariable::Get("NodeName");
|
||||
}
|
||||
|
||||
bool IcingaApplication::ResolveMacro(const String& macro, const CheckResult::Ptr&, String *result) const
|
||||
bool IcingaApplication::ResolveMacro(const String& macro, const CheckResult::Ptr&, Value *result) const
|
||||
{
|
||||
double now = Utility::GetTime();
|
||||
|
||||
|
|
|
@ -50,7 +50,7 @@ public:
|
|||
Dictionary::Ptr GetVars(void) const;
|
||||
String GetNodeName(void) const;
|
||||
|
||||
virtual bool ResolveMacro(const String& macro, const CheckResult::Ptr& cr, String *result) const;
|
||||
virtual bool ResolveMacro(const String& macro, const CheckResult::Ptr& cr, Value *result) const;
|
||||
|
||||
bool GetEnableNotifications(void) const;
|
||||
void SetEnableNotifications(bool enabled);
|
||||
|
|
|
@ -66,7 +66,7 @@ Value MacroProcessor::ResolveMacros(const Value& str, const ResolverList& resolv
|
|||
}
|
||||
|
||||
bool MacroProcessor::ResolveMacro(const String& macro, const ResolverList& resolvers,
|
||||
const CheckResult::Ptr& cr, String *result, bool *recursive_macro)
|
||||
const CheckResult::Ptr& cr, Value *result, bool *recursive_macro)
|
||||
{
|
||||
CONTEXT("Resolving macro '" + macro + "'");
|
||||
|
||||
|
@ -92,12 +92,7 @@ bool MacroProcessor::ResolveMacro(const String& macro, const ResolverList& resol
|
|||
Dictionary::Ptr vars = dobj->GetVars();
|
||||
|
||||
if (vars && vars->Contains(macro)) {
|
||||
Value value = vars->Get(macro);
|
||||
|
||||
if (value.IsObjectType<Array>())
|
||||
value = Utility::Join(value, ';');
|
||||
|
||||
*result = value;
|
||||
*result = vars->Get(macro);
|
||||
*recursive_macro = true;
|
||||
return true;
|
||||
}
|
||||
|
@ -150,9 +145,6 @@ bool MacroProcessor::ResolveMacro(const String& macro, const ResolverList& resol
|
|||
tokens[0] == "notes")
|
||||
*recursive_macro = true;
|
||||
|
||||
if (ref.IsObjectType<Array>())
|
||||
ref = Utility::Join(ref, ';');
|
||||
|
||||
*result = ref;
|
||||
return true;
|
||||
}
|
||||
|
@ -161,7 +153,7 @@ bool MacroProcessor::ResolveMacro(const String& macro, const ResolverList& resol
|
|||
return false;
|
||||
}
|
||||
|
||||
String MacroProcessor::InternalResolveMacros(const String& str, const ResolverList& resolvers,
|
||||
Value MacroProcessor::InternalResolveMacros(const String& str, const ResolverList& resolvers,
|
||||
const CheckResult::Ptr& cr, String *missingMacro,
|
||||
const MacroProcessor::EscapeCallback& escapeFn, const Dictionary::Ptr& resolvedMacros,
|
||||
bool useResolvedMacros, int recursionLevel)
|
||||
|
@ -183,7 +175,7 @@ String MacroProcessor::InternalResolveMacros(const String& str, const ResolverLi
|
|||
|
||||
String name = result.SubStr(pos_first + 1, pos_second - pos_first - 1);
|
||||
|
||||
String resolved_macro;
|
||||
Value resolved_macro;
|
||||
bool recursive_macro;
|
||||
bool found;
|
||||
|
||||
|
@ -211,10 +203,24 @@ String MacroProcessor::InternalResolveMacros(const String& str, const ResolverLi
|
|||
}
|
||||
|
||||
/* recursively resolve macros in the macro if it was a user macro */
|
||||
if (recursive_macro)
|
||||
if (recursive_macro) {
|
||||
if (resolved_macro.IsObjectType<Array>()) {
|
||||
Array::Ptr arr = resolved_macro;
|
||||
Array::Ptr result = new Array();
|
||||
|
||||
ObjectLock olock(arr);
|
||||
BOOST_FOREACH(Value& value, arr) {
|
||||
result->Add(InternalResolveMacros(value,
|
||||
resolvers, cr, missingMacro, EscapeCallback(), Dictionary::Ptr(),
|
||||
false, recursionLevel + 1));
|
||||
}
|
||||
|
||||
resolved_macro = result;
|
||||
} else
|
||||
resolved_macro = InternalResolveMacros(resolved_macro,
|
||||
resolvers, cr, missingMacro, EscapeCallback(), Dictionary::Ptr(),
|
||||
false, recursionLevel + 1);
|
||||
}
|
||||
|
||||
if (!useResolvedMacros && found && resolvedMacros)
|
||||
resolvedMacros->Set(name, resolved_macro);
|
||||
|
@ -222,8 +228,19 @@ String MacroProcessor::InternalResolveMacros(const String& str, const ResolverLi
|
|||
if (escapeFn)
|
||||
resolved_macro = escapeFn(resolved_macro);
|
||||
|
||||
/* we're done if the value is an array */
|
||||
if (resolved_macro.IsObjectType<Array>()) {
|
||||
/* don't allow mixing strings and arrays in macro strings */
|
||||
if (pos_first != 0 || pos_second != str.GetLength() - 1)
|
||||
BOOST_THROW_EXCEPTION(std::invalid_argument("Mixing both strings and non-strings in macros is not allowed."));
|
||||
|
||||
return resolved_macro;
|
||||
}
|
||||
|
||||
String resolved_macro_str = resolved_macro;
|
||||
|
||||
result.Replace(pos_first, pos_second - pos_first + 1, resolved_macro);
|
||||
offset = pos_first + resolved_macro.GetLength() + 1;
|
||||
offset = pos_first + resolved_macro_str.GetLength() + 1;
|
||||
}
|
||||
|
||||
return result;
|
||||
|
|
|
@ -37,7 +37,7 @@ namespace icinga
|
|||
class I2_ICINGA_API MacroProcessor
|
||||
{
|
||||
public:
|
||||
typedef boost::function<String (const String&)> EscapeCallback;
|
||||
typedef boost::function<Value (const Value&)> EscapeCallback;
|
||||
typedef std::pair<String, Object::Ptr> ResolverSpec;
|
||||
typedef std::vector<ResolverSpec> ResolverList;
|
||||
|
||||
|
@ -51,8 +51,8 @@ private:
|
|||
MacroProcessor(void);
|
||||
|
||||
static bool ResolveMacro(const String& macro, const ResolverList& resolvers,
|
||||
const CheckResult::Ptr& cr, String *result, bool *recursive_macro);
|
||||
static String InternalResolveMacros(const String& str,
|
||||
const CheckResult::Ptr& cr, Value *result, bool *recursive_macro);
|
||||
static Value InternalResolveMacros(const String& str,
|
||||
const ResolverList& resolvers, const CheckResult::Ptr& cr,
|
||||
String *missingMacro, const EscapeCallback& escapeFn,
|
||||
const Dictionary::Ptr& resolvedMacros, bool useResolvedMacros,
|
||||
|
|
|
@ -38,7 +38,7 @@ class I2_ICINGA_API MacroResolver
|
|||
public:
|
||||
DECLARE_PTR_TYPEDEFS(MacroResolver);
|
||||
|
||||
virtual bool ResolveMacro(const String& macro, const CheckResult::Ptr& cr, String *result) const = 0;
|
||||
virtual bool ResolveMacro(const String& macro, const CheckResult::Ptr& cr, Value *result) const = 0;
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -36,12 +36,13 @@ struct CommandArgument
|
|||
{
|
||||
int Order;
|
||||
bool SkipKey;
|
||||
bool RepeatKey;
|
||||
bool SkipValue;
|
||||
String Key;
|
||||
String Value;
|
||||
Value AValue;
|
||||
|
||||
CommandArgument(void)
|
||||
: Order(0), SkipKey(false), SkipValue(false)
|
||||
: Order(0), SkipKey(false), RepeatKey(true), SkipValue(false)
|
||||
{ }
|
||||
|
||||
bool operator<(const CommandArgument& rhs) const
|
||||
|
@ -50,6 +51,35 @@ struct CommandArgument
|
|||
}
|
||||
};
|
||||
|
||||
void PluginUtility::AddArgumentHelper(const Array::Ptr& args, const String& key, const String& value, bool add_key, bool add_value)
|
||||
{
|
||||
if (add_key)
|
||||
args->Add(key);
|
||||
|
||||
if (add_value)
|
||||
args->Add(value);
|
||||
}
|
||||
|
||||
Value PluginUtility::EscapeMacroShellArg(const Value& value)
|
||||
{
|
||||
String result;
|
||||
|
||||
if (value.IsObjectType<Array>()) {
|
||||
Array::Ptr arr = value;
|
||||
|
||||
ObjectLock olock(arr);
|
||||
BOOST_FOREACH(const Value& arg, arr) {
|
||||
if (result.GetLength() > 0)
|
||||
result += " ";
|
||||
|
||||
result += Utility::EscapeShellArg(arg);
|
||||
}
|
||||
} else
|
||||
result = Utility::EscapeShellArg(value);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
void PluginUtility::ExecuteCommand(const Command::Ptr& commandObj, const Checkable::Ptr& checkable,
|
||||
const CheckResult::Ptr& cr, const MacroProcessor::ResolverList& macroResolvers,
|
||||
const Dictionary::Ptr& resolvedMacros, bool useResolvedMacros,
|
||||
|
@ -61,7 +91,7 @@ void PluginUtility::ExecuteCommand(const Command::Ptr& commandObj, const Checkab
|
|||
Value command;
|
||||
if (!raw_arguments || raw_command.IsObjectType<Array>())
|
||||
command = MacroProcessor::ResolveMacros(raw_command, macroResolvers, cr, NULL,
|
||||
Utility::EscapeShellArg, resolvedMacros, useResolvedMacros);
|
||||
PluginUtility::EscapeMacroShellArg, resolvedMacros, useResolvedMacros);
|
||||
else {
|
||||
Array::Ptr arr = new Array();
|
||||
arr->Add(raw_command);
|
||||
|
@ -83,10 +113,14 @@ void PluginUtility::ExecuteCommand(const Command::Ptr& commandObj, const Checkab
|
|||
|
||||
if (arginfo.IsObjectType<Dictionary>()) {
|
||||
Dictionary::Ptr argdict = arginfo;
|
||||
if (argdict->Contains("key"))
|
||||
arg.Key = argdict->Get("key");
|
||||
argval = argdict->Get("value");
|
||||
if (argdict->Contains("required"))
|
||||
required = argdict->Get("required");
|
||||
arg.SkipKey = argdict->Get("skip_key");
|
||||
if (argdict->Contains("repeat_key"))
|
||||
arg.RepeatKey = argdict->Get("repeat_key");
|
||||
arg.Order = argdict->Get("order");
|
||||
|
||||
String set_if = argdict->Get("set_if");
|
||||
|
@ -118,7 +152,7 @@ void PluginUtility::ExecuteCommand(const Command::Ptr& commandObj, const Checkab
|
|||
arg.SkipValue = true;
|
||||
|
||||
String missingMacro;
|
||||
arg.Value = MacroProcessor::ResolveMacros(argval, macroResolvers,
|
||||
arg.AValue = MacroProcessor::ResolveMacros(argval, macroResolvers,
|
||||
cr, &missingMacro, MacroProcessor::EscapeCallback(), resolvedMacros,
|
||||
useResolvedMacros);
|
||||
|
||||
|
@ -152,11 +186,32 @@ void PluginUtility::ExecuteCommand(const Command::Ptr& commandObj, const Checkab
|
|||
|
||||
Array::Ptr command_arr = command;
|
||||
BOOST_FOREACH(const CommandArgument& arg, args) {
|
||||
if (!arg.SkipKey)
|
||||
command_arr->Add(arg.Key);
|
||||
Array::Ptr arr;
|
||||
|
||||
if (!arg.SkipValue)
|
||||
command_arr->Add(arg.Value);
|
||||
if (arg.AValue.IsString())
|
||||
AddArgumentHelper(command_arr, arg.Key, arg.AValue, !arg.SkipKey, !arg.SkipValue);
|
||||
else if (arg.AValue.IsObjectType<Array>())
|
||||
arr = static_cast<Array::Ptr>(arg.AValue);
|
||||
else
|
||||
continue;
|
||||
|
||||
if (arr) {
|
||||
bool first = true;
|
||||
|
||||
ObjectLock olock(arr);
|
||||
BOOST_FOREACH(const Value& value, arr) {
|
||||
bool add_key;
|
||||
|
||||
if (first) {
|
||||
first = false;
|
||||
add_key = !arg.SkipKey;
|
||||
} else
|
||||
add_key = !arg.SkipKey && arg.RepeatKey;
|
||||
|
||||
|
||||
AddArgumentHelper(command_arr, arg.Key, value, add_key, !arg.SkipValue);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -173,6 +228,9 @@ void PluginUtility::ExecuteCommand(const Command::Ptr& commandObj, const Checkab
|
|||
NULL, MacroProcessor::EscapeCallback(), resolvedMacros,
|
||||
useResolvedMacros);
|
||||
|
||||
if (value.IsObjectType<Array>())
|
||||
value = Utility::Join(value, ';');
|
||||
|
||||
envMacros->Set(kv.first, value);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -52,6 +52,9 @@ public:
|
|||
|
||||
private:
|
||||
PluginUtility(void);
|
||||
|
||||
static void AddArgumentHelper(const Array::Ptr& args, const String& key, const String& value, bool add_key, bool add_value);
|
||||
static Value EscapeMacroShellArg(const Value& value);
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -134,7 +134,7 @@ String Service::StateTypeToString(StateType type)
|
|||
return "HARD";
|
||||
}
|
||||
|
||||
bool Service::ResolveMacro(const String& macro, const CheckResult::Ptr& cr, String *result) const
|
||||
bool Service::ResolveMacro(const String& macro, const CheckResult::Ptr& cr, Value *result) const
|
||||
{
|
||||
if (macro == "state") {
|
||||
*result = StateToString(GetState());
|
||||
|
|
|
@ -43,7 +43,7 @@ public:
|
|||
|
||||
Host::Ptr GetHost(void) const;
|
||||
|
||||
virtual bool ResolveMacro(const String& macro, const CheckResult::Ptr& cr, String *result) const;
|
||||
virtual bool ResolveMacro(const String& macro, const CheckResult::Ptr& cr, Value *result) const;
|
||||
|
||||
static ServiceState StateFromString(const String& state);
|
||||
static String StateToString(ServiceState state);
|
||||
|
|
|
@ -117,11 +117,11 @@ void GraphiteWriter::CheckResultHandler(const Checkable::Ptr& checkable, const C
|
|||
String prefix;
|
||||
|
||||
if (service) {
|
||||
prefix = MacroProcessor::ResolveMacros(GetServiceNameTemplate(), resolvers, cr, NULL, &GraphiteWriter::EscapeMetric);
|
||||
prefix = MacroProcessor::ResolveMacros(GetServiceNameTemplate(), resolvers, cr, NULL, &GraphiteWriter::EscapeMacroMetric);
|
||||
|
||||
SendMetric(prefix, "state", service->GetState());
|
||||
} else {
|
||||
prefix = MacroProcessor::ResolveMacros(GetHostNameTemplate(), resolvers, cr, NULL, &GraphiteWriter::EscapeMetric);
|
||||
prefix = MacroProcessor::ResolveMacros(GetHostNameTemplate(), resolvers, cr, NULL, &GraphiteWriter::EscapeMacroMetric);
|
||||
|
||||
SendMetric(prefix, "state", host->GetState());
|
||||
}
|
||||
|
@ -214,3 +214,19 @@ String GraphiteWriter::EscapeMetric(const String& str)
|
|||
|
||||
return result;
|
||||
}
|
||||
|
||||
Value GraphiteWriter::EscapeMacroMetric(const Value& value)
|
||||
{
|
||||
if (value.IsObjectType<Array>()) {
|
||||
Array::Ptr arr = value;
|
||||
Array::Ptr result = new Array();
|
||||
|
||||
ObjectLock olock(arr);
|
||||
BOOST_FOREACH(const Value& arg, arr) {
|
||||
result->Add(EscapeMetric(arg));
|
||||
}
|
||||
|
||||
return Utility::Join(result, '.');
|
||||
} else
|
||||
return EscapeMetric(value);
|
||||
}
|
||||
|
|
|
@ -55,6 +55,7 @@ private:
|
|||
void SendMetric(const String& prefix, const String& name, double value);
|
||||
void SendPerfdata(const String& prefix, const CheckResult::Ptr& cr);
|
||||
static String EscapeMetric(const String& str);
|
||||
static Value EscapeMacroMetric(const Value& value);
|
||||
|
||||
void ReconnectTimerHandler(void);
|
||||
};
|
||||
|
|
|
@ -64,6 +64,14 @@ void PerfdataWriter::Start(void)
|
|||
RotateFile(m_HostOutputFile, GetHostTempPath(), GetHostPerfdataPath());
|
||||
}
|
||||
|
||||
Value PerfdataWriter::EscapeMacroMetric(const Value& value)
|
||||
{
|
||||
if (value.IsObjectType<Array>())
|
||||
return Utility::Join(value, ';');
|
||||
else
|
||||
return value;
|
||||
}
|
||||
|
||||
void PerfdataWriter::CheckResultHandler(const Checkable::Ptr& checkable, const CheckResult::Ptr& cr)
|
||||
{
|
||||
CONTEXT("Writing performance data for object '" + checkable->GetName() + "'");
|
||||
|
@ -86,7 +94,7 @@ void PerfdataWriter::CheckResultHandler(const Checkable::Ptr& checkable, const C
|
|||
resolvers.push_back(std::make_pair("icinga", IcingaApplication::GetInstance()));
|
||||
|
||||
if (service) {
|
||||
String line = MacroProcessor::ResolveMacros(GetServiceFormatTemplate(), resolvers, cr);
|
||||
String line = MacroProcessor::ResolveMacros(GetServiceFormatTemplate(), resolvers, cr, NULL, &PerfdataWriter::EscapeMacroMetric);
|
||||
|
||||
{
|
||||
ObjectLock olock(this);
|
||||
|
@ -96,7 +104,7 @@ void PerfdataWriter::CheckResultHandler(const Checkable::Ptr& checkable, const C
|
|||
m_ServiceOutputFile << line << "\n";
|
||||
}
|
||||
} else {
|
||||
String line = MacroProcessor::ResolveMacros(GetHostFormatTemplate(), resolvers, cr);
|
||||
String line = MacroProcessor::ResolveMacros(GetHostFormatTemplate(), resolvers, cr, NULL, &PerfdataWriter::EscapeMacroMetric);
|
||||
|
||||
{
|
||||
ObjectLock olock(this);
|
||||
|
|
|
@ -47,6 +47,7 @@ protected:
|
|||
|
||||
private:
|
||||
void CheckResultHandler(const Checkable::Ptr& checkable, const CheckResult::Ptr& cr);
|
||||
static Value EscapeMacroMetric(const Value& value);
|
||||
|
||||
Timer::Ptr m_RotationTimer;
|
||||
void RotationTimerHandler(void);
|
||||
|
|
|
@ -22,7 +22,8 @@ set(base_test_SOURCES
|
|||
base-json.cpp base-match.cpp base-netstring.cpp base-object.cpp
|
||||
base-serialize.cpp base-shellescape.cpp base-stacktrace.cpp
|
||||
base-stream.cpp base-string.cpp base-timer.cpp base-type.cpp
|
||||
base-value.cpp config-ops.cpp icinga-perfdata.cpp test.cpp
|
||||
base-value.cpp config-ops.cpp icinga-macros.cpp icinga-perfdata.cpp
|
||||
test.cpp
|
||||
)
|
||||
|
||||
set_property(SOURCE test.cpp PROPERTY EXCLUDE_UNITY_BUILD TRUE)
|
||||
|
@ -90,6 +91,7 @@ add_boost_test(base
|
|||
base_value/format
|
||||
config_ops/simple
|
||||
config_ops/advanced
|
||||
icinga_macros/simple
|
||||
icinga_perfdata/empty
|
||||
icinga_perfdata/simple
|
||||
icinga_perfdata/quotes
|
||||
|
|
|
@ -0,0 +1,55 @@
|
|||
/******************************************************************************
|
||||
* Icinga 2 *
|
||||
* Copyright (C) 2012-2014 Icinga Development Team (http://www.icinga.org) *
|
||||
* *
|
||||
* This program is free software; you can redistribute it and/or *
|
||||
* modify it under the terms of the GNU General Public License *
|
||||
* as published by the Free Software Foundation; either version 2 *
|
||||
* of the License, or (at your option) any later version. *
|
||||
* *
|
||||
* This program 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 for more details. *
|
||||
* *
|
||||
* You should have received a copy of the GNU General Public License *
|
||||
* along with this program; if not, write to the Free Software Foundation *
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. *
|
||||
******************************************************************************/
|
||||
|
||||
#include "icinga/macroprocessor.hpp"
|
||||
#include <boost/test/unit_test.hpp>
|
||||
|
||||
using namespace icinga;
|
||||
|
||||
BOOST_AUTO_TEST_SUITE(icinga_macros)
|
||||
|
||||
BOOST_AUTO_TEST_CASE(simple)
|
||||
{
|
||||
Dictionary::Ptr macrosA = new Dictionary();
|
||||
macrosA->Set("testA", 7);
|
||||
macrosA->Set("testB", "hello");
|
||||
|
||||
Dictionary::Ptr macrosB = new Dictionary();
|
||||
macrosB->Set("testA", 3);
|
||||
macrosB->Set("testC", "world");
|
||||
|
||||
Array::Ptr testD = new Array();
|
||||
testD->Add(3);
|
||||
testD->Add("test");
|
||||
|
||||
macrosB->Set("testD", testD);
|
||||
|
||||
MacroProcessor::ResolverList resolvers;
|
||||
resolvers.push_back(std::make_pair("macrosA", macrosA));
|
||||
resolvers.push_back(std::make_pair("macrosB", macrosB));
|
||||
|
||||
BOOST_CHECK(MacroProcessor::ResolveMacros("$macrosA.testB$ $macrosB.testC$", resolvers) == "hello world");
|
||||
BOOST_CHECK(MacroProcessor::ResolveMacros("$testA$", resolvers) == "7");
|
||||
|
||||
Array::Ptr result = MacroProcessor::ResolveMacros("$testD$", resolvers);
|
||||
BOOST_CHECK(result->GetLength() == 2);
|
||||
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_SUITE_END()
|
Loading…
Reference in New Issue