thalassa/lib/scriptpp/scrtest.cpp

1558 lines
61 KiB
C++
Raw Permalink Normal View History

2026-03-19 01:23:52 +00:00
// +-------------------------------------------------------------------------+
// | Script Plus Plus vers. 0.3.72 |
// | Copyright (c) Andrey V. Stolyarov <croco at croco dot net> 2003--2023 |
// | ----------------------------------------------------------------------- |
// | This is free software. Permission is granted to everyone to use, copy |
// | or modify this software under the terms and conditions of |
// | GNU LESSER GENERAL PUBLIC LICENSE, v. 2.1 |
// | as published by Free Software Foundation (see the file LGPL.txt) |
// | |
// | Please visit http://www.croco.net/software/scriptpp to get a fresh copy |
// | ----------------------------------------------------------------------- |
// | This code is provided strictly and exclusively on the "AS IS" basis. |
// | !!! THERE IS NO WARRANTY OF ANY KIND, NEITHER EXPRESSED NOR IMPLIED !!! |
// +-------------------------------------------------------------------------+
#include <stdio.h>
#include <unistd.h>
#include "tests.h"
#include "scrvar.hpp"
#include "scrvect.hpp"
#include "scrmap.hpp"
#include "scrsubs.hpp"
#include "scrmacro.hpp"
#include "conffile.hpp"
#include "confinfo.hpp"
#include "scrmsg.hpp"
class PrefReq : public ScriptSubstitutionPrefixRequest {
public:
PrefReq() : ScriptSubstitutionPrefixRequest("req") {}
ScriptVariable Handle(const ScriptVector &v) const {
ScriptVariable res;
for(int i = 0; i < v.Length(); i++) {
res += '(';
res += v[i];
res += ')';
}
return res;
}
};
class MacroFunc : public ScriptMacroprocessorMacro {
public:
MacroFunc(const char *nm = "req", bool dirty = false)
: ScriptMacroprocessorMacro("req") {}
ScriptVariable Expand(const ScriptVector &v) const {
ScriptVariable res;
for(int i = 0; i < v.Length(); i++) {
res += '(';
res += v[i];
res += ')';
}
return res;
}
ScriptVariable Expand() const { return "<empty>"; }
};
class MacroQuote : public ScriptMacroprocessorMacro {
public:
MacroQuote() : ScriptMacroprocessorMacro("q") {}
ScriptVariable Expand(const ScriptVector &v) const {
return v[0];
}
ScriptVariable Expand() const { return "<empty>"; }
};
int main()
{
try {
test_suite("ScriptVariable");
test_subsuite("construction");
{
ScriptVariable v1("a");
test_long("a", v1.length(), 1);
ScriptVariable v2("");
test_long("empty", v2.length(), 0);
}
test_subsuite("valid_and_invalid");
{
ScriptVariable v1("a");
ScriptVariable v2("");
ScriptVariable v3(0);
ScriptVariableInv v4;
ScriptVariable v5((char*)0);
test("str_valid", v1.IsValid() && !v1.IsInvalid());
test("empty_str_valid", v2.IsValid() && !v2.IsInvalid());
test("zero_invalid", !v3.IsValid() && v3.IsInvalid());
test("inv_invalid", !v4.IsValid() && v4.IsInvalid());
test("null_ptr_invalid", !v5.IsValid() && v5.IsInvalid());
}
test_subsuite("assignments");
{
ScriptVariable v1;
v1 = "abc";
test_long("length", v1.length(), 3);
test_str("c_str", v1.c_str(), "abc");
}
test_subsuite("addition");
{
ScriptVariable abc("abc");
ScriptVariable res = abc + '.' + abc + '.' + abc;
test_long("added_length", res.length(), 11);
test_str("added_str", res.c_str(), "abc.abc.abc");
}
test_subsuite("substirng");
{
ScriptVariable v1;
v1 = "abcdefgh";
ScriptVariable::Substring s1(v1, 0, 100);
test_str("sub1", s1.Get().c_str(), "abcdefgh");
ScriptVariable::Substring s2(v1, 0, 1);
test_str("sub2", s2.Get().c_str(), "a");
ScriptVariable::Substring s3(v1, 0, 3);
test_str("sub3", s3.Get().c_str(), "abc");
ScriptVariable::Substring s4(v1, 3, 3);
test_str("sub4", s4.Get().c_str(), "def");
ScriptVariable::Substring s5(v1, 3, 10000);
test_str("sub5", s5.Get().c_str(), "defgh");
ScriptVariable::Substring s6(v1, -5, 2);
test_str("negative", s6.Get().c_str(), "de");
ScriptVariable::Substring s7(v1, 0, 0);
test_str("empty", s7.Get().c_str(), "");
test("empty_eq", s7.Get() == ScriptVariable(""));
v1.Range(-1,1).Erase();
test_str("remove_last_char", v1.c_str(), "abcdefg");
ScriptVariable v2;
v2 = "abcdefgh";
ScriptVariable::Substring(v2, 2, 2).Erase();
test_str("erase", v2.c_str(), "abefgh");
ScriptVariable::Substring(v2, 3, 200).Erase();
test_str("erase_to_end", v2.c_str(), "abe");
ScriptVariable v3("alpha->beta");
ScriptVariable::Substring s20 = v3.Strstr("->");
test_str("substring_find", s20.Get().c_str(), "->");
test_str("substring_before", s20.Before().Get().c_str(), "alpha");
test_str("substring_after", s20.After().Get().c_str(), "beta");
}
test_subsuite("strchr");
{
ScriptVariable v1;
v1 = "abcdefgeh";
ScriptVariable::Substring sub;
sub = v1.Strchr('e');
test("strchr_valid", sub.IsValid());
test("strchr_not_invalid", !sub.IsInvalid());
test_str("strchr", sub.Get().c_str(), "e");
test_long("strchr_left", sub.Index(), 4);
sub = v1.Strchr('q');
test("strchr_invalid", sub.IsInvalid());
test("strchr_not_valid", !sub.IsValid());
sub = v1.Strrchr('e');
test("strrchr_valid", sub.IsValid());
test("strrchr_not_invalid", !sub.IsInvalid());
test_str("strrchr", sub.Get().c_str(), "e");
test_long("strrchr_right", sub.Index(), 7);
}
test_subsuite("strstr");
{
ScriptVariable v1;
v1 = "abcdefghdefpqr";
ScriptVariable::Substring sub;
sub = v1.Strstr("def");
test("strstr_valid", sub.IsValid());
test("strstr_not_invalid", !sub.IsInvalid());
test_str("strstr", sub.Get().c_str(), "def");
test_long("strstr", sub.Index(), 3);
sub = v1.Strstr("deg");
test("strstr_invalid", sub.IsInvalid());
test("strstr_not_valid", !sub.IsValid());
}
test_subsuite("strrstr");
{
ScriptVariable v1;
v1 = "abcdefghdefpqr";
ScriptVariable::Substring sub;
sub = v1.Strrstr("def");
test("strrstr_valid", sub.IsValid());
test("strrstr_not_invalid", !sub.IsInvalid());
test_str("strrstr", sub.Get().c_str(), "def");
test_long("strrstr", sub.Index(), 8);
sub = v1.Strrstr("deg");
test("strrstr_invalid", sub.IsInvalid());
test("strrstr_not_valid", !sub.IsValid());
}
test_subsuite("upperlower");
{
ScriptVariable v1 = "abcDEFpqrXZY123=-";
v1.Toupper();
test_str("toupper", v1.c_str(), "ABCDEFPQRXZY123=-");
ScriptVariable v2 = "abcDEFpqrXZY123=-";
v2.Tolower();
test_str("tolower", v2.c_str(), "abcdefpqrxzy123=-");
}
test_subsuite("trim");
{
{
ScriptVariable v1;
v1 = " abc ";
ScriptVariable::Substring Sub(v1);
Sub.Trim(" ");
test_str("trim", Sub.Get().c_str(), "abc");
}
{
ScriptVariable v1;
v1 = "abc";
ScriptVariable::Substring Sub(v1);
Sub.Trim(".");
test_str("trim_noop", Sub.Get().c_str(), "abc");
}
{
ScriptVariable v1;
v1 = "a";
ScriptVariable::Substring Sub(v1);
Sub.Trim(".");
test_str("trim_noop", Sub.Get().c_str(), "a");
}
{
ScriptVariable v1;
v1 = "........";
ScriptVariable::Substring Sub(v1);
Sub.Trim(".");
test_str("trim_all", Sub.Get().c_str(), "");
}
{
ScriptVariable v1;
v1 = " abc ";
v1.Trim(" ");
test_str("trim_sv", v1.c_str(), "abc");
}
}
test_subsuite("prefix");
{
ScriptVariable v("abcdefgh");
test("prefix1", v.HasPrefix("a"));
test("prefix2", v.HasPrefix("ab"));
test("prefix3", v.HasPrefix("abc"));
test("prefix4", v.HasPrefix("abcd"));
test("prefix5", v.HasPrefix("abcde"));
test("empty_prefix", v.HasPrefix(""));
test("prefix_self", v.HasPrefix("abcdefgh"));
test("super_prefix", !v.HasPrefix("abcdefghij"));
test("prefix_fail", !v.HasPrefix("abcd1"));
test("prefix_fail2", !v.HasPrefix("12345"));
}
test_subsuite("suffix");
{
ScriptVariable v("abcdefgh");
test("suffix1", v.HasSuffix("h"));
test("suffix2", v.HasSuffix("gh"));
test("suffix3", v.HasSuffix("fgh"));
test("suffix4", v.HasSuffix("efgh"));
test("suffix5", v.HasSuffix("defgh"));
test("empty_suffix", v.HasSuffix(""));
test("suffix_self", v.HasSuffix("abcdefgh"));
test("super_suffix", !v.HasSuffix("pqabcdefgh"));
test("suffix_fail", !v.HasSuffix("1efgh"));
test("suffix_fail2", !v.HasSuffix("12345"));
}
test_subsuite("suffix_v");
{
ScriptVariable v("abcdefgh");
test("suffix1", v.HasSuffix(ScriptVariable("h")));
test("suffix2", v.HasSuffix(ScriptVariable("gh")));
test("suffix3", v.HasSuffix(ScriptVariable("fgh")));
test("suffix4", v.HasSuffix(ScriptVariable("efgh")));
test("suffix5", v.HasSuffix(ScriptVariable("defgh")));
test("empty_suffix", v.HasSuffix(ScriptVariable("")));
test("suffix_self", v.HasSuffix(ScriptVariable("abcdefgh")));
test("super_suffix", !v.HasSuffix(ScriptVariable("pqabcdefgh")));
test("suffix_fail", !v.HasSuffix(ScriptVariable("1efgh")));
test("suffix_fail2", !v.HasSuffix(ScriptVariable("12345")));
}
test_subsuite("fetch words");
{
ScriptVariable v1;
v1 = " abc def ghijh q ";
ScriptVariable::Substring iter(v1);
ScriptVariable::Substring word;
test("first_word", iter.FetchWord(word));
test_str("first_word_value", word.Get().c_str(), "abc");
test("second_word", iter.FetchWord(word));
test_str("second_word_value", word.Get().c_str(), "def");
test("third_word", iter.FetchWord(word));
test_str("third_word_value", word.Get().c_str(), "ghijh");
test("fourth_word", iter.FetchWord(word));
test_str("fourth_word_value", word.Get().c_str(), "q");
test("no_more_words", !iter.FetchWord(word));
ScriptVariable v2;
v2 = "abc def ghijh q ";
ScriptVariable::Substring iter2(v2);
test("first_word_at_begin", iter2.FetchWord(word));
test_str("first_word_at_begin_value", word.Get().c_str(), "abc");
ScriptVariable v3;
v3 = "abc";
ScriptVariable::Substring iter3(v3);
test("first_word_the_only", iter3.FetchWord(word));
test_str("first_word_the_only", word.Get().c_str(), "abc");
test("first_word_the_only_ends", !iter3.FetchWord(word));
ScriptVariable v4;
v4 = " ";
ScriptVariable::Substring iter4(v4);
test("no_words", !iter4.FetchWord(word));
ScriptVariable v5;
ScriptVariable::Substring iter5(v5);
test("empty_no_words", !iter5.FetchWord(word));
}
test_subsuite("fetch tokens");
{
ScriptVariable v1;
v1 = "abc,def,ghijh,q,qqqq";
ScriptVariable::Substring iter(v1);
ScriptVariable::Substring word;
test("first_token", iter.FetchToken(word));
test_str("first_token_value", word.Get().c_str(), "abc");
test("second_token", iter.FetchToken(word));
test_str("second_token_value", word.Get().c_str(), "def");
test("third_token", iter.FetchToken(word));
test_str("third_token_value", word.Get().c_str(), "ghijh");
test("fourth_token", iter.FetchToken(word));
test_str("fourth_token_value", word.Get().c_str(), "q");
test("fifth_token", iter.FetchToken(word));
test_str("fifth_token_value", word.Get().c_str(), "qqqq");
test("no_more_tokens", !iter.FetchToken(word));
ScriptVariable v2;
v2 = "abc, def, ghijh , q ";
ScriptVariable::Substring iter2(v2);
test("first_token_at_begin", iter2.FetchToken(word));
test_str("first_token_at_begin_value", word.Get().c_str(), "abc");
ScriptVariable v3;
v3 = "abc";
ScriptVariable::Substring iter3(v3);
test("first_token_the_only", iter3.FetchToken(word));
test_str("first_token_the_only", word.Get().c_str(), "abc");
test("first_token_the_only_ends", !iter3.FetchToken(word));
ScriptVariable v4;
v4 = " ";
ScriptVariable::Substring iter4(v4);
test("spaces_only_token_string", iter4.FetchToken(word, " "));
test_str("empty_token", word.Get().c_str(), "");
#if 0 // this is found to be inconsistent!
ScriptVariable v5;
ScriptVariable::Substring iter5(v5);
test("empty_no_tokens", !iter5.FetchToken(word));
#endif
ScriptVariable v6(",,");
ScriptVariable::Substring iter6(v6);
test("empty_token_begin", iter6.FetchToken(word));
test_str("empty_token_begin_empty", word.Get().c_str(), "");
test("empty_token_middle", iter6.FetchToken(word));
test_str("middle_token_middle_empty", word.Get().c_str(), "");
test("empty_token_end", iter6.FetchToken(word));
test_str("empty_token_end_empty", word.Get().c_str(), "");
ScriptVariable v7("klkjds lsafj lfjd lfj");
ScriptVariable::Substring iter7(v7);
ScriptVariable::Substring iter7got =
iter7.FetchToken("\n");
test_str("whole_string", iter7got.Get().c_str(),
v7.Whole().Get().c_str());
}
test_subsuite("iterator words");
{
ScriptVariable v1;
v1 = " abc def ghijh q ";
ScriptVariable::Iterator iter(v1);
test("first_word", iter.NextWord());
test_str("first_word_value", iter.Get().c_str(), "abc");
test("second_word", iter.NextWord());
test_str("second_word_value", iter.Get().c_str(), "def");
test("third_word", iter.NextWord());
test_str("third_word_value", iter.Get().c_str(), "ghijh");
test("fourth_word", iter.NextWord());
test_str("fourth_word_value", iter.Get().c_str(), "q");
test("no_more_words", !iter.NextWord());
ScriptVariable v2;
v2 = "abc def ghijh q ";
ScriptVariable::Iterator iter2(v2);
test("first_word_at_begin", iter2.NextWord());
test_str("first_word_at_begin_value", iter2.Get().c_str(), "abc");
ScriptVariable v3;
v3 = "abc";
ScriptVariable::Iterator iter3(v3);
test("first_word_the_only", iter3.NextWord());
test_str("first_word_the_only", iter3.Get().c_str(), "abc");
test("first_word_the_only_ends", !iter3.NextWord());
ScriptVariable v4;
v4 = " ";
ScriptVariable::Iterator iter4(v4);
test("no_words", !iter4.NextWord());
ScriptVariable v5;
ScriptVariable::Iterator iter5(v5);
test("empty_no_words", !iter5.NextWord());
}
test_subsuite("iterator tokens");
{
ScriptVariable v1;
v1 = "abc,def,ghijh,q,qqqq";
ScriptVariable::Iterator iter(v1);
test("first_token", iter.NextToken());
test_str("first_token_value", iter.Get().c_str(), "abc");
test("second_token", iter.NextToken());
test_str("second_token_value", iter.Get().c_str(), "def");
test("third_token", iter.NextToken());
test_str("third_token_value", iter.Get().c_str(), "ghijh");
test("fourth_token", iter.NextToken());
test_str("fourth_token_value", iter.Get().c_str(), "q");
test("fifth_token", iter.NextToken());
test_str("fifth_token_value", iter.Get().c_str(), "qqqq");
test("no_more_tokens", !iter.NextToken());
ScriptVariable v2;
v2 = "abc,def,ghijh,q";
ScriptVariable::Iterator iter2(v2);
test("first_token_at_begin", iter2.NextToken());
test_str("first_token_at_begin_value", iter2.Get().c_str(), "abc");
ScriptVariable v3;
v3 = "abc";
ScriptVariable::Iterator iter3(v3);
test("first_token_the_only", iter3.NextToken());
test_str("first_token_the_only", iter3.Get().c_str(), "abc");
test("first_token_the_only_ends", !iter3.NextToken());
ScriptVariable v4;
v4 = " ";
ScriptVariable::Iterator iter4(v4);
test("spaces_only_token_string", iter4.NextToken(":", " "));
test_str("empty_token", iter4.Get().c_str(), "");
#if 0 // this found to be inconsistent!
ScriptVariable v5;
ScriptVariable::Iterator iter5(v5);
test("empty_no_tokens", !iter5.NextToken());
#endif
ScriptVariable v6(",,");
ScriptVariable::Iterator iter6(v6);
test("empty_token_begin", iter6.NextToken());
test_str("empty_token_begin_empty", iter6.Get().c_str(), "");
test("empty_token_middle", iter6.NextToken());
test_str("middle_token_middle_empty", iter6.Get().c_str(), "");
test("empty_token_end", iter6.NextToken());
test_str("empty_token_end_empty", iter6.Get().c_str(), "");
}
test_subsuite("iterator words backwards");
{
ScriptVariable v1;
v1 = " abc def ghijh pqr ";
ScriptVariable::Iterator iter(v1);
test("last_word", iter.PrevWord());
test_str("last_word_value", iter.Get().c_str(), "pqr");
test("second_word", iter.PrevWord());
test_str("second_word_value", iter.Get().c_str(), "ghijh");
test("third_word", iter.PrevWord());
test_str("third_word_value", iter.Get().c_str(), "def");
test("fourth_word", iter.PrevWord());
test_str("fourth_word_value", iter.Get().c_str(), "abc");
test("no_more_words", !iter.PrevWord());
ScriptVariable v2;
v2 = " abc def ghijh pqr";
ScriptVariable::Iterator iter2(v2);
test("last_word_at_end", iter2.PrevWord());
test_str("last_word_at_end_value", iter2.Get().c_str(), "pqr");
ScriptVariable v3;
v3 = "abc";
ScriptVariable::Iterator iter3(v3);
test("last_word_the_only", iter3.PrevWord());
test_str("last_word_the_only", iter3.Get().c_str(), "abc");
test("last_word_the_only_ends", !iter3.PrevWord());
ScriptVariable v4;
v4 = " ";
ScriptVariable::Iterator iter4(v4);
test("no_words", !iter4.PrevWord());
ScriptVariable v5;
ScriptVariable::Iterator iter5(v5);
test("empty_no_words", !iter5.PrevWord());
}
test_subsuite("iterator tokens backwards");
{
ScriptVariable v1;
v1 = "abc,def,ghijh,q,pqr";
ScriptVariable::Iterator iter(v1);
test("last_token", iter.PrevToken());
test_str("last_token_value", iter.Get().c_str(), "pqr");
test("second_token", iter.PrevToken());
test_str("second_token_value", iter.Get().c_str(), "q");
test("third_token", iter.PrevToken());
test_str("third_token_value", iter.Get().c_str(), "ghijh");
test("fourth_token", iter.PrevToken());
test_str("fourth_token_value", iter.Get().c_str(), "def");
test("fifth_token", iter.PrevToken());
test_str("fifth_token_value", iter.Get().c_str(), "abc");
test("no_more_tokens", !iter.PrevToken());
ScriptVariable v2;
v2 = "abc,def,ghijh,pqr";
ScriptVariable::Iterator iter2(v2);
test("last_token_at_end", iter2.PrevToken());
test_str("last_token_at_end_value", iter2.Get().c_str(), "pqr");
ScriptVariable v3;
v3 = "abc";
ScriptVariable::Iterator iter3(v3);
test("last_token_the_only", iter3.PrevToken());
test_str("last_token_the_only", iter3.Get().c_str(), "abc");
test("last_token_the_only_ends", !iter3.PrevToken());
ScriptVariable v4;
v4 = " ";
ScriptVariable::Iterator iter4(v4);
test("spaces_only_token_string", iter4.PrevToken(":", " "));
test_str("empty_token", iter4.Get().c_str(), "");
#if 0 // this found to be inconsistent!
ScriptVariable v5;
ScriptVariable::Iterator iter5(v5);
test("empty_no_tokens", !iter5.PrevToken());
#endif
ScriptVariable v6(",,");
ScriptVariable::Iterator iter6(v6);
test("back_empty_token_end", iter6.PrevToken());
test_long("back_empty_token_len_zero", iter6.Length(), 0);
test_str("back_empty_token_end_empty", iter6.Get().c_str(), "");
test("back_empty_token_middle", iter6.PrevToken());
test_str("middle_token_middle_back_empty", iter6.Get().c_str(), "");
test("back_empty_token_begin", iter6.PrevToken());
test_str("back_empty_token_begin_empty", iter6.Get().c_str(), "");
}
test_subsuite("iterator mixed words/tokens");
{
ScriptVariable v1;
v1 = " justaword ignoredword : secondtoken";
ScriptVariable::Iterator iter(v1);
test("mix_first_word", iter.NextWord());
test_str("mix_first_token_value", iter.Get().c_str(), "justaword");
test("mix_second_token", iter.NextToken(":", " "));
test_str("mix_second_token_value", iter.Get().c_str(), "secondtoken");
}
test_subsuite("vsprintf");
{
ScriptVariable v1(10, "%d%d", 56, 78);
test_str("vsprintf_sufficient_room", v1.c_str(), "5678");
test_long("vsprintf_len", v1.length(), 4);
ScriptVariable v2(10, "%d%s%d", 56,
"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
78);
test_str("vsprintf_insufficient_room", v2.c_str(), "56"
"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
"78");
}
test_subsuite("numbers");
{
test_str("int_0", ScriptNumber(0).c_str(), "0");
test_str("int_25", ScriptNumber(25).c_str(), "25");
test_str("int_neg25", ScriptNumber(-25).c_str(), "-25");
test_str("int_12345678", ScriptNumber(12345678).c_str(), "12345678");
test_str("maxint", ScriptNumber(0x7fffffff).c_str(), "2147483647");
int i = 0x80000001;
//int i = -2147483647;
test_str("minint_plus_1", ScriptNumber(i).c_str(), "-2147483647");
i = 0x80000000;
test_str("minint", ScriptNumber(i).c_str(), "-2147483648");
unsigned int ui = 0x80000000;
test_str("minint_unsigned", ScriptNumber(ui).c_str(), "2147483648");
unsigned long long big = 0;
big = ~big;
big >>= 1; // now it is max_long_long
long long signed_big = big;
test_str("maxlonglong", ScriptNumber(signed_big).c_str(),
"9223372036854775807");
signed_big = ~signed_big; // now it is min_long_long
test_str("minlonglong", ScriptNumber(signed_big).c_str(),
"-9223372036854775808");
}
test_subsuite("getting_numbers");
{
{
ScriptVariable v1("257");
long x;
v1.GetLong(x);
test_long("get_long", x, 257);
}
{
ScriptVariable v1("0x25bc");
long x;
v1.GetLong(x);
test_long("get_hex_long", x, 0x25bc);
}
{
ScriptVariable v1("17.15");
long n,m;
v1.GetRational(n, m);
test_long("get_rational_n", n, 1715);
test_long("get_rational_m", m, 100);
}
}
test_subsuite("vector");
{
ScriptVector vec1(" word1 word2 word3 word4");
test_str("word1", vec1[0].c_str(), "word1");
test_str("word2", vec1[1].c_str(), "word2");
test_str("word3", vec1[2].c_str(), "word3");
test_str("word4", vec1[3].c_str(), "word4");
test_str("join", vec1.Join().c_str(), "word1word2word3word4");
test_str("join2", vec1.Join("->").c_str(),
"word1->word2->word3->word4");
ScriptVector vec2(" token1 : token2:: token3 :token4",
":", " ");
test_str("token1", vec2[0].c_str(), "token1");
test_str("token2", vec2[1].c_str(), "token2");
test_str("token3", vec2[2].c_str(), "");
test_str("token4", vec2[3].c_str(), "token3");
test_str("token5", vec2[4].c_str(), "token4");
ScriptVector vec3("a b");
vec3[15] = "c";
test_long("index_changes_length", vec3.Length(), 16);
ScriptVector vec4(" abrakadabra ", ",", " \t\n\r");
test_long("vector_from_single_token", vec4.Length(), 1);
test_str("single_token_in_vector", vec4[0].c_str(), "abrakadabra");
ScriptVector vec5;
ScriptVariable abrakadabra(" abrakadabra ");
vec5 = ScriptVector(abrakadabra, ",", " \t\n\r");
test_long("vector_from_single_token_assg", vec4.Length(), 1);
test_str("single_token_in_vector_assg",
vec4[0].c_str(), "abrakadabra");
ScriptVector vec6("aaa bbb ccc ddd eee fff");
test_str("vector_join_segment", vec6.Join(">>", 3).c_str(),
"ddd>>eee>>fff");
test_str("vector_join_segment2", vec6.Join(">>>", 3, 2).c_str(),
"ddd>>>eee");
test_str("vector_join_segment3", vec6.Join(">>>", 100, 200).c_str(),
"");
test_long("vector_join_segment3a", vec6.Length(), 6);
}
test_subsuite("subvector");
{
ScriptVector vec1("word1 word2 word3 word4");
ScriptVector vec2(vec1, 2);
test_str("second_half", vec2.Join(" ").c_str(), "word3 word4");
ScriptVector vec3(vec1, 2, 1);
test_str("part2_1", vec3.Join(" ").c_str(), "word3");
ScriptVector vec4(vec1, 4, 1);
test_str("outranged", vec4.Join(" ").c_str(), "");
ScriptVector vec5(vec1, 2, 0);
test_str("zerolength", vec5.Join(" ").c_str(), "");
}
test_subsuite("vector part remove");
{
{
ScriptVector vec("word1 word2 word3 word4 word5");
vec.Remove(1, 1);
test_str("vector_remove_1_1", vec.Join(" ").c_str(),
"word1 word3 word4 word5");
}
{
ScriptVector vec("word1 word2 word3 word4 word5");
vec.Remove(1, 3);
test_str("vector_remove_1_3", vec.Join(" ").c_str(),
"word1 word5");
}
{
ScriptVector vec("word1 word2 word3 word4 word5");
vec.Remove(2, 10);
test_str("vector_remove_2_many", vec.Join(" ").c_str(),
"word1 word2");
}
{
ScriptVector vec("word1 word2 word3");
vec.Remove(2, 1);
test_str("vector_remove_last", vec.Join(" ").c_str(),
"word1 word2");
test_long("vector_remove_last_len", vec.Length(), 2);
}
{
ScriptVector vec("word1 word2 word3");
vec.Remove(2);
test_str("vector_remove_last_all", vec.Join(" ").c_str(),
"word1 word2");
test_long("vector_remove_last_all_len", vec.Length(), 2);
}
}
test_subsuite("vector larger remove");
{
int len;
for(len = 20; len < 100; len++) {
ScriptVector v;
int i;
for(i = 0; i < len; i++)
v.AddItem(ScriptVariable("str")+ScriptNumber(i));
v.Remove(0, len-15);
ScriptVariable testname =
ScriptVariable("vector_large_remove_") +
ScriptNumber(len);
test_long(testname.c_str(), v.Length(), 15);
}
}
test_subsuite("vector insertion");
{
ScriptVector vec("word1 word2 word3 word4 word5 word6");
int i;
for(i = 0; i < 1000; i++)
vec.Insert(3, ScriptVariable("inserted_")+ScriptNumber(i));
test_long("vector_insertion_1000", vec.Length(), 1006);
}
test_subsuite("vector assignment");
{
ScriptVector vec("a b", " ");
vec = ScriptVector("abra schwabra kadabra babra", " ,\t\n");
test_long("vector_assignment_len", vec.Length(), 4);
vec = ScriptVector("a", " ,\t\n");
test_long("vector_assignment_len_shrink", vec.Length(), 1);
}
test_subsuite("resize bug");
{
{
ScriptVariable v("/usr/src/linux");
ScriptVariable::Substring s = v.Strrchr('/');
s.Move(1);
test_str("move_1", s.Get().c_str(), "l");
test_long("move_idx", s.Index(), 9);
test_long("move_len", s.Length(), 1);
s.Resize(v.Length());
test_str("resize_max", s.Get().c_str(), "linux");
test_long("resize_max_idx", s.Index(), 9);
//test_long("resize_max_len", s.Length(), 5);
s.Erase();
test_str("erase", v.c_str(), "/usr/src/");
}
{
ScriptVariable v("0123456789");
ScriptVariable::Substring s(v, 5, 15);
s.Replace("abc");
test_str("replace_long", v.c_str(), "01234abc");
}
}
test_subsuite("extend");
{
ScriptVariable v("0123456789");
ScriptVariable::Substring s(v, 5, 1);
s.ExtendToBegin();
test_str("extend_to_begin", s.Get().c_str(), "012345");
ScriptVariable::Substring s2(v, 5, 1);
s2.ExtendToEnd();
test_str("extend_to_end", s2.Get().c_str(), "56789");
}
test_subsuite("setlength");
{
ScriptVariable v("0123456789");
ScriptVariable::Substring s(v, 5, 2);
s.SetLength(3);
test_str("setlength", s.Get().c_str(), "567");
ScriptVariable::Substring s2(v, 3, 3);
s2.SetLength(500);
test_str("setlength_too_many", s2.Get().c_str(), "3456789");
ScriptVariable::Substring s3(v, 3, 3);
s3.SetLength(-1);
test_str("setlength_negative", s3.Get().c_str(), "3456789");
}
test_subsuite("numbers");
{
test_str("short", ScriptNumber((short int) 275).c_str(), "275");
test_str("ushort", ScriptNumber((unsigned short) 57275).c_str(),
"57275");
test_str("int", ScriptNumber((int) 275).c_str(), "275");
test_str("uint", ScriptNumber((unsigned int) 57275).c_str(),
"57275");
test_str("long", ScriptNumber((long) 275).c_str(), "275");
test_str("ulong", ScriptNumber((unsigned long) 57275).c_str(),
"57275");
test_str("double", ScriptNumber(27.2727).c_str(), "27.2727");
test_str("prec", ScriptNumber(27.123456789, 3).c_str(), "27.123");
test_str("prec_l", ScriptNumber(27.123, 5).c_str(), "27.12300");
ScriptNumber sn(751);
ScriptVariable ns3 = sn+' '+sn+' '+sn;
test_long("join_numbers_len", ns3.length(), 11);
test_str("join_numbers", ns3.c_str(), "751 751 751");
}
test_subsuite("ScriptSet");
{
ScriptSet set;
test_long("empty_set", set.Count(), 0);
set.AddItem("Mary");
set.AddItem("Jane");
set.AddItem("Mr. Very Long Name, Jr.");
test_long("set_count", set.Count(), 3);
test("present", set.Contains("Jane"));
test("present2", set.Contains("Mary"));
test("not_present", !set.Contains("Harry"));
test_long("set_count_unchanged", set.Count(), 3);
int cw = 0;
for(int i=0; i<1000; i++) {
ScriptNumber sn(i);
ScriptVariable str = sn + ' ' + sn + ' ' + sn;
if(!set.AddItem(str))
printf(" COULDNT ADD %d\n", i);
if(set.Count() != i + 4 - cw) {
printf(" WRONG: i==%d, count==%ld\n",
i, set.Count());
cw++;
}
}
test_long("set_count_big", set.Count(), 1003);
test("present_after_resize", set.Contains("Mary"));
test("still_not_present", !set.Contains("Harry"));
test("present_long", set.Contains("0 0 0"));
test("present_long751", set.Contains("751 751 751"));
}
test_subsuite("ScriptMap");
{
ScriptMap map;
test_long("empty_map", map.Count(), 0);
map.AddItem("Mary", "Little Mary");
map.AddItem("Jane", "Big Jane");
map.AddItem("Mr. Very Long Name, Jr.", "Bobby");
test_long("map_count", map.Count(), 3);
test_str("get", map.GetItem("Jane").c_str(), "Big Jane");
test_str("get2", map.GetItem("Mary").c_str(), "Little Mary");
test("not_present", map.GetItem("Harry").IsInvalid());
test_long("map_count_unchanged", map.Count(), 3);
int cw = 0;
for(int i=0; i<1000; i++) {
ScriptNumber sn(i);
ScriptVariable str = sn + ' ' + sn + ' ' + sn;
if(!map.AddItem(str, sn))
printf(" COULDNT ADD %d\n", i);
if(map.Count() != i + 4 - cw) {
printf(" WRONG: i==%d, count==%ld\n",
i, map.Count());
cw++;
}
}
test_long("map_count_big", map.Count(), 1003);
test_str("getafterresize", map.GetItem("Jane").c_str(),"Big Jane");
test_str("getafterresize2", map.GetItem("Mary").c_str(),
"Little Mary");
test("still_not_present", map.GetItem("Harry").IsInvalid());
test_str("get_long", map.GetItem("0 0 0").c_str(), "0");
test_str("get_long751", map.GetItem("751 751 751").c_str(), "751");
ScriptMap m2;
m2["Anna"] += "Little Ann";
m2["Liza"] += "Pretty Liza";
m2["Anna"] += " sleeps deep";
test_str("index_operator", m2["Liza"].c_str(), "Pretty Liza");
test_str("index_operator2", m2["Anna"].c_str(),
"Little Ann sleeps deep");
}
test_subsuite("ScriptMacroprocessor");
{
ScriptMacroprocessor s;
s.AddMacro(new ScriptMacroConst("foo", "well-bar"));
ScriptVariable v;
s.AddMacro(new ScriptMacroScrVar("x", &v));
test_str("macro_const", s("foo%foo% %foo%").c_str(),
"foowell-bar well-bar");
test_str("macro_const_misname", s("foo%foor% %foo%").c_str(),
"foo%foor% well-bar");
test_str("macro_percent", s("foo%%foo %% %%foo%%").c_str(),
"foo%foo % %foo%");
ScriptVariableInv inval;
test("macro_preserves_invalstring", s(inval).IsInvalid());
v = "hell";
test_str("macro_var", s("go to %x%!!").c_str(), "go to hell!!");
v = "heaven";
test_str("macro_var2", s("go to %x%!!").c_str(), "go to heaven!!");
ScriptVector vv("shit happens twice");
s.SetPositionals(vv, false);
test_str("macro_argv", s("%2% %1% %0%").c_str(),
"twice happens shit");
test_str("macro_allargs", s("abc%*%def").c_str(),
"abchappens twicedef");
ScriptMacroprocessor s2;
ScriptVector vv2(
"shit happens twice and once again and then another time");
s2.SetPositionals(vv2, 2, 4, false);
test_str("macro_argv_idx", s2("%3% %2% %1% %0%").c_str(),
"again once and twice");
test_str("macro_allargs_idx", s2("%*%").c_str(),
"and once again");
ScriptMacroprocessor s3;
ScriptVector vv3("shit happens twice");
test_str("macro_with_argv", s3("%2% %1% %0%", vv3).c_str(),
"twice happens shit");
test_str("macro_with_argv_allargs", s3("abc%*%def", vv3).c_str(),
"abchappens twicedef");
}
test_subsuite("ScriptMacroFunctions");
{
ScriptMacroprocessor s;
s.AddMacro(new MacroFunc);
test_str("macro_paramreq", s("foo%req:John:Doe:Idiot%bar").c_str(),
"foo(John)(Doe)(Idiot)bar");
test_str("macro_paramreq_noparam", s("foo%req%bar").c_str(),
"foo<empty>bar");
}
test_subsuite("ScriptMacroNested");
{
ScriptMacroprocessor s;
s.AddMacro(new ScriptMacroConst("f1", "foo"));
s.AddMacro(new ScriptMacroConst("b1", "bar"));
s.AddMacro(new ScriptMacroConst("foobar", "WellDone"));
test_str("macro_no_nesting_in_names", s("ttt%[%f1%%b1%]eee").c_str(),
"ttt%[%f1%%b1%]eee");
ScriptMacroprocessor s2;
s2.AddMacro(new MacroFunc);
s2.AddMacro(new ScriptMacroConst("f1", "foo"));
s2.AddMacro(new ScriptMacroConst("f2", "bar"));
s2.AddMacro(new ScriptMacroConst("f3", "bur"));
test_str("macro_nested2",
s2("nnn%[req:%f1%:%[req:%f2%:%f3%]]aaa").c_str(),
"nnn(foo)((bar)(bur))aaa");
}
test_subsuite("ScriptMacro only one level");
{
ScriptMacroprocessor s;
s.AddMacro(new ScriptMacroConst("attack", "CRACKED"));
s.AddMacro(new ScriptMacroConst("suspect", "%[attack]"));
s.AddMacro(new ScriptMacroConst("unaware", "%[suspect]"));
test_str("macro_args_in_eager_inj_safe",
s("ttt%[unaware]eee").c_str(),
"ttt%[suspect]eee");
}
test_subsuite("ScriptMacro dictionaries");
{
const char *v[] = { "foo", "bar", "abra", "kadabra", 0 };
ScriptVector dd(v);
ScriptMacroDictionary dict("dd", dd);
ScriptMacroprocessor s;
s.AddMacro(new ScriptMacroConst("a", "bcd"));
test_str("dictionary",
s.Process("%a% %dd:abra% %dd:foo%", &dict).c_str(),
"bcd kadabra bar");
}
test_subsuite("ScriptMacro Lazy");
{
ScriptMacroprocessor s;
s.AddMacro(new ScriptMacroConst("foobar", "foo:bar"));
s.AddMacro(new ScriptMacroConst("abrakadabra", "abra:kadabra"));
s.AddMacro(new MacroFunc);
s.AddMacro(new MacroQuote);
test_str("too_simple_lazy",
s("ttt%{foobar}eee").c_str(),
"tttfoo:bareee");
test_str("simple_lazy",
s("ttt%{req:abc:def:ghi}eee").c_str(),
"ttt(abc)(def)(ghi)eee");
test_str("simple_lazy_quoted_closer",
s("ttt%{req:abc:d%}f:ghi}eee").c_str(),
"ttt(abc)(d}f)(ghi)eee");
test_str("macro_nested_eager_innder_delimiter_kept",
s("ttt%[req:%foobar%:%abrakadabra%]eee").c_str(),
"ttt(foo:bar)(abra:kadabra)eee");
test_str("macro_nested_lazy",
s("ttt%{req:%foobar%:%abrakadabra% }eee").c_str(),
"ttt(foo:bar)(abra:kadabra )eee");
test_str("macro_nested_lazy_esc_before_real_closer",
s("ttt%{req:%foobar%:%abrakadabra%}eee").c_str(),
"ttt(foo:bar)(abra:kadabra)eee");
test_str("macro_nested_lazy_2",
s("ttt%{req:%foobar%:%[abrakadabra]}eee").c_str(),
"ttt(foo:bar)(abra:kadabra)eee");
test_str("macro_nested_lazy_in_lazy",
s("ttt%{req: %{foobar} }eee").c_str(),
"ttt( foo:bar )eee");
test_str("macro_nested_lazy_in_lazy_2",
s("ttt%{req:%{foobar}:%{abrakadabra}}eee").c_str(),
"ttt(foo:bar)(abra:kadabra)eee");
test_str("macro_nested_lazy_in_lazy_with_esc",
s("ttt%{req:%{foobar}:%}:%{abrakadabra}}eee").c_str(),
"ttt(foo:bar)(})(abra:kadabra)eee");
test_str("macro_lazy_in_eager", s("ttt%[req:%{foobar}]eee").c_str(),
"ttt(foo:bar)eee");
test_str("macro_lazy_req_in_req", s("%{req:%{req:a}}").c_str(),
"((a))");
test_str("quote", s("%[q:abc]").c_str(), "abc");
test_str("macro_lazy_req_in_nr",
s("x%[q:z%{req:a}t]y").c_str(), "xz(a)ty");
ScriptVector vv("shit happens twice");
test_str("macro_argv_in_lazy",
s("ttt%{req:%1%:%2%:%[0]}eee", vv).c_str(),
"ttt(happens)(twice)(shit)eee");
}
test_subsuite("ScriptMacro Lazy safety");
{
ScriptMacroprocessor s;
s.AddMacro(new ScriptMacroConst("attack", "CRACKED"));
s.AddMacro(new ScriptMacroConst("suspect", "%[attack]"));
s.AddMacro(new MacroFunc);
test_str("macro_injection_in_lazy",
s("ttt%{req:%{suspect}}eee").c_str(),
"ttt(CRACKED)eee");
test_str("macro_eager_in_lazy_inj_safe",
s("ttt%{req:%[suspect]}eee").c_str(),
"ttt(%[attack])eee");
test_str("macro_eager_in_double_lazy_inj_safe",
s("ttt%{req:a:%{req:%[suspect]}:b}eee").c_str(),
"ttt(a)((%[attack]))(b)eee");
}
test_subsuite("ScriptMacro eager argument injection protection");
{
ScriptMacroprocessor s;
s.AddMacro(new ScriptMacroConst("attack", "CRACKED"));
s.AddMacro(new ScriptMacroConst("suspect", "%[attack]"));
s.AddMacro(new ScriptMacroConst("unaware", "%[suspect]"));
s.AddMacro(new MacroFunc);
test_str("macro_args_in_eager_inj_safe",
s("ttt%[req:%[unaware]:%[unaware]]eee").c_str(),
"ttt(%[suspect])(%[suspect])eee");
}
test_subsuite("ScriptMacro Lazy infinity protection");
{
ScriptMacroprocessor s;
s.AddMacro(new ScriptMacroConst("a", "%{a}"));
test_str("macro_loop_safety", s("%{a}").c_str(), "%{a}");
}
test_subsuite("ScriptMacro scoping");
{
ScriptMacroprocessor s;
s.AddMacro(new ScriptMacroConst("abra", "kadabra"));
ScriptMacroprocessor s2(&s);
s2.AddMacro(new ScriptMacroConst("foo", "bar"));
test_str("macro_scoped_processors", s2("%abra% %foo%").c_str(),
"kadabra bar");
}
test_subsuite("ScriptMacro invalidated string");
{
fflush(stdout);
ScriptMacroprocessor s;
s.AddMacro(new MacroFunc);
s.AddMacro(new ScriptMacroConst("inval", ScriptVariableInv()));
test_str("macro_inval_tolerance", s("%[req:%inval%]").c_str(),
"(%inval%)");
test_str("macro_inval_tolerance2", s("%[req:a%inval%b]").c_str(),
"(a%inval%b)");
}
test_subsuite("ScriptMacro unknown variable");
{
ScriptMacroprocessor s;
s.AddMacro(new ScriptMacroConst("abra", "kadabra"));
test_str("macro_keeps_unknown", s("%foo%").c_str(), "%foo%");
test_str("macro_keeps_unkn2", s("a%foo%b").c_str(), "a%foo%b");
test_str("macro_keeps_unkn3", s("%[foo]").c_str(), "%[foo]");
test_str("macro_keeps_unkn4", s("a%[foo]b").c_str(), "a%[foo]b");
}
test_subsuite("ScriptMacro positionals after call");
{
// this test was added in suspection for a bug,
// only to show there's no bug
ScriptMacroprocessor s;
s.AddMacro(new ScriptMacroConst("abra", "kadabra"));
s.AddMacro(new MacroFunc);
ScriptVector v("zero one two three", " ");
ScriptVariable res = s.Process("a %0% %[req:%1%:b] c %2% d", v);
test_str("macro_poss_after_call", res.c_str(),
"a zero (one)(b) c two d");
}
test_subsuite("ScriptMacro Apply method");
{
ScriptMacroprocessor s;
s.AddMacro(new ScriptMacroConst("abra", "kadabra"));
s.AddMacro(new MacroFunc);
s.AddMacro(new MacroFunc("bad", true));
ScriptVector args;
args.AddItem("foo");
args.AddItem("bar");
args.AddItem("bur");
ScriptVariable res = s.Apply("req", args);
test_str("macro_apply", res.c_str(), "(foo)(bar)(bur)");
ScriptVariable res2 = s.Apply("bad", args);
test("macro_apply_dirty_blocked", res2.IsInvalid());
}
test_subsuite("ScriptSubst");
{
ScriptSubstitution s;
s.AddVar(new ScriptSubstitutionConst("foo", "well-bar"));
ScriptVariable v;
s.AddVar(new ScriptSubstitutionScrVar("x", &v));
test_str("subs_const", s("foo%foo% %foo%").c_str(),
"foowell-bar well-bar");
test_str("subs_const_misname", s("foo%foo % %foo%").c_str(),
"foo%foo % well-bar");
test_str("subs_percent", s("foo%%foo %% %%foo%%").c_str(),
"foo%foo % %foo%");
v = "hell";
test_str("subs_var", s("go to %x%!!").c_str(), "go to hell!!");
v = "heaven";
test_str("subs_var2", s("go to %x%!!").c_str(), "go to heaven!!");
ScriptVector vv("shit happens twice");
s.AddVar(new ScriptSubstitutionArgv(&vv, false));
test_str("subs_argv", s("%2% %1% %0%").c_str(),
"twice happens shit");
test_str("subs_allargs", s("abc%*%def").c_str(),
"abchappens twicedef");
ScriptSubstitution s2;
ScriptVector vv2(
"shit happens twice and once again and then another time");
s2.AddVar(new ScriptSubstitutionArgv(&vv2, false, 2, 4));
test_str("subs_argv_idx", s2("%3% %2% %1% %0%").c_str(),
"again once and twice");
test_str("subs_allargs_idx", s2("%*%").c_str(),
"and once again");
ScriptSubstitution s3;
ScriptVector vv3("shit happens twice");
test_str("subs_with_argv", s3("%2% %1% %0%", vv3).c_str(),
"twice happens shit");
test_str("subs_with_argv_allargs", s3("abc%*%def", vv3).c_str(),
"abchappens twicedef");
}
test_subsuite("ScriptSubstPrefixReq");
{
ScriptSubstitution s;
s.AddVar(new PrefReq);
test_str("subs_paramreq", s("foo%req:John:Doe:Idiot%bar").c_str(),
"foo(John)(Doe)(Idiot)bar");
test_str("subs_paramreq_require_delim", s("foo%req--%bar").c_str(),
"foo%req--%bar");
}
test_subsuite("ScriptSubstNested");
{
ScriptSubstitution s;
s.AddVar(new ScriptSubstitutionConst("f1", "foo"));
s.AddVar(new ScriptSubstitutionConst("b1", "bar"));
s.AddVar(new ScriptSubstitutionConst("foobar", "WellDone"));
test_str("subs_nested", s("ttt%[%f1%%b1%]eee").c_str(),
"tttWellDoneeee");
ScriptSubstitution s2;
s2.AddVar(new ScriptSubstitutionConst("f1", "foo"));
s2.AddVar(new ScriptSubstitutionConst("foo15", "bar"));
s2.AddVar(new ScriptSubstitutionConst("xfoobarz", "WellDone"));
test_str("subs_nested2", s2("nnn%[xfoo%[%[f1]15]z]aaa").c_str(),
"nnnWellDoneaaa");
}
test_subsuite("ScriptSubst Lazy");
{
ScriptSubstitution s;
s.AddVar(new ScriptSubstitutionConst("foobar", "foo:bar"));
s.AddVar(new ScriptSubstitutionConst("abrakadabra", "abra:kadabra"));
s.AddVar(new PrefReq);
test_str("subs_nested_eager",
s("ttt%[req:%foobar%:%abrakadabra%]eee").c_str(),
"ttt(foo)(bar)(abra)(kadabra)eee");
test_str("subs_nested_lazy",
s("ttt%{req:%foobar%:%abrakadabra% }eee").c_str(),
"ttt(foo:bar)(abra:kadabra )eee");
test_str("subs_nested_lazy_2",
s("ttt%{req:%foobar%:%[abrakadabra]}eee").c_str(),
"ttt(foo:bar)(abra:kadabra)eee");
test_str("subs_nested_lazy_in_lazy",
s("ttt%{req:%{foobar}:%{abrakadabra}}eee").c_str(),
"ttt(foo:bar)(abra:kadabra)eee");
test_str("subs_nested_lazy_in_lazy_with_esc",
s("ttt%{req:%{foobar}:%}:%{abrakadabra}}eee").c_str(),
"ttt(foo:bar)(})(abra:kadabra)eee");
test_str("subs_lazy_in_eager", s("ttt%[req:%{foobar}]eee").c_str(),
"ttt(foo)(bar)eee");
test_str("subs_lazy_req_in_req", s("%{req:%{req:a}}").c_str(),
"((a))");
s.AddVar(new ScriptSubstitutionConst("(a)", "ok"));
test_str("subs_lazy_req_in_nr", s("%[%{req:a}]").c_str(), "ok");
ScriptVector vv("shit happens twice");
test_str("subs_argv_in_lazy",
s("ttt%{req:%1%:%2%:%[0]}eee", vv).c_str(),
"ttt(happens)(twice)(shit)eee");
}
test_subsuite("ScriptSubst Lazy safety");
{
ScriptSubstitution s;
s.AddVar(new ScriptSubstitutionConst("attack", "CRACKED"));
s.AddVar(new ScriptSubstitutionConst("suspect", "%[attack]"));
s.AddVar(new PrefReq);
test_str("subs_injection_in_lazy",
s("ttt%{req:%{suspect}}eee").c_str(),
"ttt(CRACKED)eee");
test_str("subs_eager_in_lazy_inj_safe",
s("ttt%{req:%[suspect]}eee").c_str(),
"ttt(%[attack])eee");
test_str("subs_eager_in_double_lazy_inj_safe",
s("ttt%{req:a:%{req:%[suspect]}:b}eee").c_str(),
"ttt(a)((%[attack]))(b)eee");
}
test_subsuite("ScriptSubst Lazy infinity protection");
{
ScriptSubstitution s;
s.AddVar(new ScriptSubstitutionConst("a", "%{a}"));
fflush(stdout);
test_str("subs_loop_safety", s("%{a}").c_str(), "%{a}");
}
test_subsuite("ScriptSubst dictionaries");
{
const char *v[] = { "foo", "bar", "abra", "kadabra", 0 };
ScriptVector dd(v);
ScriptSubstitutionDictionary dict(dd);
ScriptSubstitution s;
s.AddVar(new ScriptSubstitutionConst("a", "bcd"));
test_str("dictionary",
s.Substitute("%a% %abra% %foo%", &dict).c_str(),
"bcd kadabra bar");
}
test_subsuite("ScriptSubst keep unreplaced");
{
ScriptSubstitution s;
s.AddVar(new ScriptSubstitutionConst("a", "XYZ"));
test_str("simple_kept", s.Substitute("%a% %bcde%").c_str(),
"XYZ %bcde%");
test_str("lazy_inmost_kept", s.Substitute("%{a} %{bcde}").c_str(),
"XYZ %{bcde}");
test_str("active_inmost_kept", s.Substitute("%[a] %[bcde]").c_str(),
"XYZ %[bcde]");
}
test_subsuite("ReadConfigFile");
{
const char *fnm = "___test";
FILE *f = fopen(fnm, "w");
if(f) {
fputs("foo = bar\n"
"abra = schwabra\n+ kadabra\n"
"punk = is\n not\n dead\n", f);
fclose(f);
ReadConfigFileToVector rcf;
rcf.FOpen(fnm);
ScriptVector v;
bool res = rcf.ReadTo(v);
test("conffile_to_vec_success", res);
test_long("conffile_to_vec_count", v.Length(), 6);
test_str("conffile_to_vec_name1", v[0].c_str(), "foo");
test_str("conffile_to_vec_name2", v[2].c_str(), "abra");
test_str("conffile_to_vec_name3", v[4].c_str(), "punk");
test_str("conffile_to_vec_simple_val", v[1].c_str(), "bar");
test_str("conffile_to_vec_plus_val", v[3].c_str(),
"schwabra\n kadabra");
test_str("conffile_to_vec_spc_val", v[5].c_str(),
"is\nnot\ndead");
f = fopen(fnm, "w");
fputs("name15 = value15\n", f);
fclose(f);
rcf.FOpen(fnm);
res = rcf.ReadTo(v);
test("conffile_to_vec_again_success", res);
test_str("conffile_to_vec_again_name", v[6].c_str(), "name15");
test_str("conffile_to_vec_again_val", v[7].c_str(), "value15");
unlink(fnm);
} else {
fprintf(stderr, "couldn't create test file!\n");
}
}
test_subsuite("ReadConfigFile2");
{
const char *fnm = "___test";
FILE *f = fopen(fnm, "w");
if(f) {
fputs("alpha = sunday\n"
"beta = monday\n"
"gamma = tuesday\n"
"foo = bar %{alpha} bur\n", f);
fclose(f);
ConfigInformation info;
info.FOpen(fnm);
info.RunParser();
test_str("confinfo_val", info.GetValue("foo").c_str(),
"bar sunday bur");
unlink(fnm);
} else {
fprintf(stderr, "couldn't create test file!\n");
}
}
test_subsuite("HeadedTextMessage");
{
#define BODYBODY "Now the body comes into play\n"
HeadedTextMessage msg(false);
const char msgtext[] =
"JustAHeader: just a value\n"
"AnotherLongerHeader: it has its value, too\n"
"ThisIsFoldedHeader: the value of this header\n"
" is so long that it has to be folded\n"
"\n"
BODYBODY;
const char *str = msgtext;
while(*str) {
msg.FeedChar(*str);
str++;
}
msg.FeedChar(-1);
int errcode, errline;
test("parsing_ok", !msg.Error(errcode, errline));
test_long("has_three_headers", msg.GetHeaders().Length(), 6);
test_long("body_length", msg.GetBody().Length(), sizeof(BODYBODY)-1);
test_str("first_header", msg.GetHeaders()[0].c_str(), "JustAHeader");
test_str("first_header_val", msg.GetHeaders()[1].c_str(),
"just a value");
test_str("last_header", msg.GetHeaders()[4].c_str(),
"ThisIsFoldedHeader");
test_str("folded_value", msg.GetHeaders()[5].c_str(),
"the value of this header\nis so long that it has to be folded");
#undef BODYBODY
}
test_subsuite("HeadedTextMessage2");
{
HeadedTextMessage msg(false);
const char msgtext[] =
"JustAHeader: just a value\n"
"AnotherLongerHeader: it has its value, too\n";
const char *str = msgtext;
while(*str) {
msg.FeedChar(*str);
if(msg.InBody()) {
test("not_in_body", false);
break;
}
str++;
}
test("not_in_body", true);
msg.FeedChar('\n');
test("in_body", msg.InBody());
const char bodytext[] = "this\n is \n a body\n";
str = bodytext;
while(*str) {
msg.FeedChar(*str);
if(!msg.InBody()) {
test("in_body2", false);
break;
}
str++;
}
test("in_body2", true);
}
test_subsuite("HeadedTextMessage3");
{
HeadedTextMessage msg(false);
const char msgtext[] =
"JustAHeader: just a value\n"
"AnotherLongerHeader: it has its value, too\n"
"ThisIsFoldedHeader: the value of this header\n"
" is so long that it has to be folded\n"
"This is broken header\n"
"\n"
"And here goes the body\n";
const char *str = msgtext;
while(*str) {
msg.FeedChar(*str);
str++;
}
msg.FeedChar(-1);
int errcode, errline;
test("parsing_fails", msg.Error(errcode, errline));
}
test_subsuite("HeadedTextMessage4");
{
HeadedTextMessage msg(false);
const char msgtext[] =
"JustAHeader: just a value\n"
"AnotherLongerHeader: it has its value, too\n"
"WellDouble: alpha\n"
"ThisIsFoldedHeader: the value of this header\n"
" is so long that it has to be folded\n"
"WellDouble: beta\n"
"\n"
"And here goes the body\n";
const char *str = msgtext;
while(*str) {
msg.FeedChar(*str);
str++;
}
msg.FeedChar(-1);
test_str("get_header", msg.FindHeader("WellDouble").c_str(), "alpha");
ScriptVector h;
msg.FindHeaders("WellDouble", h);
test_long("get_multiheader_num", h.Length(), 2);
test_str("get_multiheader_1", h[0].c_str(), "alpha");
test_str("get_multiheader_2", h[1].c_str(), "beta");
}
test_subsuite("HeadedTextMessage5");
{
HeadedTextMessage msg(true);
const char msgtext[] =
"from me to you\n"
"JustAHeader: just a value\n"
"AnotherLongerHeader: it has its value, too\n"
"WellDouble: alpha\n"
"Abra: kadabra\n"
"ThisIsFoldedHeader: the value of this header\n"
" is so long that it has to be folded\n"
"WellDouble: beta\n"
"\n"
"And here goes the body\n";
const char *str = msgtext;
while(*str) {
msg.FeedChar(*str);
str++;
}
msg.FeedChar(-1);
test_long("removing_headers", msg.RemoveHeader("WellDouble"), 2);
test_long("removing_headers1", msg.RemoveHeader("Abra"), 1);
test_long("removing_headers0", msg.RemoveHeader("Abrakadabra"), 0);
msg.SetHeader("JustAHeader", "another value");
msg.SetHeader("AddedHeader", "must go last\neven in two lines");
msg.SetHeadingLine("from you to me");
msg.SetBody("Yeah, the body here goes\n");
ScriptVariable ser = msg.Serialize();
const char *expect =
"from you to me\n"
"JustAHeader: another value\n"
"AnotherLongerHeader: it has its value, too\n"
"ThisIsFoldedHeader: the value of this header\n"
"\tis so long that it has to be folded\n"
"AddedHeader: must go last\n"
"\teven in two lines\n"
"\n"
"Yeah, the body here goes\n";
const char *p = ser.c_str();
int i;
for(i = 0; ; i++) {
if(p[i] != expect[i]) {
printf("DIFFERENCE at %d\n", i);
printf("E:[%s]\nR:[%s]\n", expect+i, p+i);
break;
}
if(!p[i])
break;
}
test_str("serialization_after_manipulations", p, expect);
}
test_subsuite("HeadedTextMessage6");
{
HeadedTextMessage msg(false);
const char msgtext[] =
"One: \xC8\xD5\xCA\xFF\n"
"Two: \xD0\xC9\xDA\xFF\xC4\xC1\n"
"\n"
"body\n";
const char *str = msgtext;
while(*str) {
msg.FeedChar((unsigned char)*str);
str++;
}
test_str("header_with_xFF", msg.FindHeader("One").c_str(),
"\xC8\xD5\xCA\xFF");
test_str("header_with_xFF_in_middle", msg.FindHeader("Two").c_str(),
"\xD0\xC9\xDA\xFF\xC4\xC1");
test_str("body_after_xFF", msg.GetBody().c_str(), "body\n");
}
test_score();
}
catch(...) {
printf("Something strange caught\n");
}
return 0;
}