mirror of
https://github.com/GothenburgBitFactory/taskwarrior.git
synced 2025-06-26 10:54:26 +02:00

- Backslashes actually. The escaping mechanism in the low-level parser was eating leading \ characters when it should not. Very hard bug to find, trivial to fix. - Added unit tests to several components while narrowing this down.
182 lines
5.8 KiB
C++
182 lines
5.8 KiB
C++
////////////////////////////////////////////////////////////////////////////////
|
|
// taskwarrior - a command line task list manager.
|
|
//
|
|
// Copyright 2006-2012, Paul Beckingham, Federico Hernandez.
|
|
//
|
|
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
// of this software and associated documentation files (the "Software"), to deal
|
|
// in the Software without restriction, including without limitation the rights
|
|
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
// copies of the Software, and to permit persons to whom the Software is
|
|
// furnished to do so, subject to the following conditions:
|
|
//
|
|
// The above copyright notice and this permission notice shall be included
|
|
// in all copies or substantial portions of the Software.
|
|
//
|
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
|
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
|
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
// SOFTWARE.
|
|
//
|
|
// http://www.opensource.org/licenses/mit-license.php
|
|
//
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
#include <iostream>
|
|
#include <JSON.h>
|
|
#include <test.h>
|
|
#include <Context.h>
|
|
|
|
Context context;
|
|
|
|
const char *positive_tests[] =
|
|
{
|
|
"{}",
|
|
|
|
" { } ",
|
|
|
|
"[]",
|
|
|
|
"{\"one\":1}",
|
|
|
|
"{\n\"one\"\n:\n1\n}\n",
|
|
|
|
"{\"name\":123, \"array\":[1,2,3.4], \"object\":{\"m1\":\"v1\", \"m2\":\"v2\"}}",
|
|
|
|
"{\"name\":\"value\",\"array\":[\"one\",\"two\"],\"object\":{\"name2\":123,\"literal\":false}}",
|
|
|
|
"{\n"
|
|
"\"ticket\": { \"type\":\"add\", \"client\":\"taskwarrior 2.x\"},\n"
|
|
"\"auth\": { \"user\":\"paul\", \"org\":\"gbf\", \"key\":\".........\",\n"
|
|
" \"locale\":\"en-US\" },\n"
|
|
"\n"
|
|
"\"add\": { \"description\":\"Wash the dog\",\n"
|
|
" \"project\":\"home\",\n"
|
|
" \"due\":\"20101101T000000Z\" }\n"
|
|
"}",
|
|
|
|
"{"
|
|
"\"ticket\":{"
|
|
"\"type\":\"synch\","
|
|
"\"client\":\"taskd-test-suite 1.0\""
|
|
"},"
|
|
"\"synch\":{"
|
|
"\"user\":{"
|
|
"\"data\":["
|
|
"{"
|
|
"\"uuid\":\"11111111-1111-1111-1111-111111111111\","
|
|
"\"status\":\"pending\","
|
|
"\"description\":\"This is a test\","
|
|
"\"entry\":\"20110111T124000Z\""
|
|
"}"
|
|
"],"
|
|
"\"synch\":\"key\""
|
|
"}"
|
|
"},"
|
|
"\"auth\":{"
|
|
"\"org\":\"gbf\","
|
|
"\"user\":\"Paul Beckingham\","
|
|
"\"key\":\"K\","
|
|
"\"locale\":\"en-US\""
|
|
"}"
|
|
"}"
|
|
};
|
|
|
|
#define NUM_POSITIVE_TESTS (sizeof (positive_tests) / sizeof (positive_tests[0]))
|
|
|
|
const char *negative_tests[] =
|
|
{
|
|
"",
|
|
"{",
|
|
"}",
|
|
"[",
|
|
"]",
|
|
"foo",
|
|
"[?]"
|
|
};
|
|
|
|
#define NUM_NEGATIVE_TESTS (sizeof (negative_tests) / sizeof (negative_tests[0]))
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
int main (int argc, char** argv)
|
|
{
|
|
UnitTest t (NUM_POSITIVE_TESTS + NUM_NEGATIVE_TESTS + 22);
|
|
|
|
// Positive tests.
|
|
for (int i = 0; i < NUM_POSITIVE_TESTS; ++i)
|
|
{
|
|
try
|
|
{
|
|
json::value* root = json::parse (positive_tests[i]);
|
|
t.ok (root, std::string ("positive: ") + positive_tests[i]);
|
|
if (root)
|
|
{
|
|
t.diag (root->dump ());
|
|
delete root;
|
|
}
|
|
}
|
|
|
|
catch (const std::string& e) { t.diag (e); }
|
|
catch (...) { t.diag ("Unknown error"); }
|
|
}
|
|
|
|
// Negative tests.
|
|
for (int i = 0; i < NUM_NEGATIVE_TESTS; ++i)
|
|
{
|
|
try
|
|
{
|
|
json::value* root = json::parse (negative_tests[i]);
|
|
t.is (root, NULL, std::string ("negative: ") + negative_tests[i]);
|
|
}
|
|
|
|
catch (const std::string& e) { t.pass (e); }
|
|
catch (...) { t.fail ("Unknown error"); }
|
|
}
|
|
|
|
// Other tests.
|
|
try
|
|
{
|
|
// Regular unit tests.
|
|
t.is (json::encode ("1\b2"), "1\\b2", "json::encode \\b -> \\\\b");
|
|
t.is (json::decode ("1\\b2"), "1\b2", "json::decode \\\\b -> \\b");
|
|
|
|
t.is (json::encode ("1\n2"), "1\\n2", "json::encode \\n -> \\\\n");
|
|
t.is (json::decode ("1\\n2"), "1\n2", "json::decode \\\\n -> \\n");
|
|
|
|
t.is (json::encode ("1\r2"), "1\\r2", "json::encode \\r -> \\\\r");
|
|
t.is (json::decode ("1\\r2"), "1\r2", "json::decode \\\\r -> \\r");
|
|
|
|
t.is (json::encode ("1\t2"), "1\\t2", "json::encode \\t -> \\\\t");
|
|
t.is (json::decode ("1\\t2"), "1\t2", "json::decode \\\\t -> \\t");
|
|
|
|
t.is (json::encode ("1\\2"), "1\\\\2", "json::encode \\ -> \\\\");
|
|
t.is (json::decode ("1\\\\2"), "1\\2", "json::decode \\\\ -> \\");
|
|
|
|
t.is (json::encode ("1\x2"), "1\x2", "json::encode \\x -> \\x (NOP)");
|
|
t.is (json::decode ("1\x2"), "1\x2", "json::decode \\x -> \\x (NOP)");
|
|
|
|
t.is (json::encode ("1€2"), "1€2", "json::encode € -> €");
|
|
t.is (json::decode ("1\\u20ac2"), "1€2", "json::decode \\u20ac -> €");
|
|
|
|
std::string encoded = json::encode ("one\\");
|
|
t.is (encoded, "one\\\\", "json::encode one\\\\ -> one\\\\\\\\");
|
|
t.is ((int)encoded.length (), 5, "json::encode one\\\\ -> length 5");
|
|
t.is (encoded[0], 'o', "json::encode one\\\\[0] -> o");
|
|
t.is (encoded[1], 'n', "json::encode one\\\\[1] -> n");
|
|
t.is (encoded[2], 'e', "json::encode one\\\\[2] -> e");
|
|
t.is (encoded[3], '\\', "json::encode one\\\\[3] -> \\");
|
|
t.is (encoded[4], '\\', "json::encode one\\\\[4] -> \\");
|
|
|
|
t.is (json::decode (encoded), "one\\", "json::decode one\\\\\\\\ -> one\\\\");
|
|
}
|
|
|
|
catch (std::string& e) {t.diag (e);}
|
|
|
|
return 0;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|