// +-------------------------------------------------------------------------+ // | Script Plus Plus vers. 0.3.72 | // | Copyright (c) Andrey V. Stolyarov 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 #include #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 ""; } }; class MacroQuote : public ScriptMacroprocessorMacro { public: MacroQuote() : ScriptMacroprocessorMacro("q") {} ScriptVariable Expand(const ScriptVector &v) const { return v[0]; } ScriptVariable Expand() const { return ""; } }; 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(), "foobar"); } 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; }