Regex
- Implemented RegX class to maintain a separate compile, and match
method, thereby allowing efficient re-use of the regex. This is
critical to Expression::eval, where an identical regex might be
applied to every task.
- Obsoleted rx.{h,cpp}, which combined the compile and match steps
into a single call, and is therefore not efficient when used in
the context of filtering.
- Fixed some unit tests that weren't building. Now they do. They
don't work of course (don't be silly) but that's a problem for
another day.
- Modified all code that relies on rx.h to use RegX.h.
This commit is contained in:
@@ -7,9 +7,9 @@ include_directories (${CMAKE_SOURCE_DIR}
|
||||
${TASK_INCLUDE_DIRS})
|
||||
|
||||
set (test_SRCS arguments.t att.t autocomplete.t color.t config.t date.t
|
||||
directory.t dom.t duration.t file.t filt.t i18n.t json.t lexer.t
|
||||
list.t nibbler.t path.t record.t rx.t seq.t t.benchmark.t t.t
|
||||
taskmod.t tdb.t tdb2.t text.t uri.t util.t variant.t view.t
|
||||
directory.t dom.t duration.t file.t i18n.t json.t lexer.t list.t
|
||||
nibbler.t path.t record.t rx.t t.benchmark.t t.t taskmod.t tdb.t
|
||||
tdb2.t text.t uri.t util.t variant.t view.t
|
||||
json_test)
|
||||
|
||||
add_custom_target (test ./run_all DEPENDS ${test_SRCS}
|
||||
|
||||
168
test/filt.t.cpp
168
test/filt.t.cpp
@@ -1,168 +0,0 @@
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// taskwarrior - a command line task list manager.
|
||||
//
|
||||
// Copyright 2006 - 2011, Paul Beckingham, Federico Hernandez.
|
||||
// All rights reserved.
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or modify it under
|
||||
// the terms of the GNU General Public License as published by the Free Software
|
||||
// Foundation; either version 2 of the License, or (at your option) any later
|
||||
// version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
// FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
||||
// details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License along with
|
||||
// this program; if not, write to the
|
||||
//
|
||||
// Free Software Foundation, Inc.,
|
||||
// 51 Franklin Street, Fifth Floor,
|
||||
// Boston, MA
|
||||
// 02110-1301
|
||||
// USA
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
#include <main.h>
|
||||
#include <test.h>
|
||||
#include <Filter.h>
|
||||
#include <Task.h>
|
||||
|
||||
Context context;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
int main (int argc, char** argv)
|
||||
{
|
||||
UnitTest test (20);
|
||||
|
||||
// Create a filter consisting of two Att criteria.
|
||||
Filter f;
|
||||
f.push_back (Att ("name1", "value1"));
|
||||
f.push_back (Att ("name2", "value2"));
|
||||
test.is (f.size (), (size_t)2, "Filter created");
|
||||
|
||||
// Create a Task to match against.
|
||||
Task yes;
|
||||
yes.set ("name1", "value1");
|
||||
yes.set ("name2", "value2");
|
||||
test.ok (f.pass (yes), "full match");
|
||||
|
||||
yes.set ("name3", "value3");
|
||||
test.ok (f.pass (yes), "over match");
|
||||
|
||||
// Negative tests.
|
||||
Task no0;
|
||||
test.notok (f.pass (no0), "no match against default Task");
|
||||
|
||||
Task no1;
|
||||
no1.set ("name3", "value3");
|
||||
test.notok (f.pass (no1), "no match against mismatch Task");
|
||||
|
||||
Task partial;
|
||||
partial.set ("name1", "value1");
|
||||
test.notok (f.pass (partial), "no match against partial Task");
|
||||
|
||||
// Modifiers.
|
||||
Task mods;
|
||||
mods.set ("name", "value");
|
||||
mods.set ("description", "hello, world.");
|
||||
|
||||
Att a ("name", "is", "value");
|
||||
f.clear ();
|
||||
f.push_back (a);
|
||||
test.ok (f.pass (mods), "name:value -> name.is:value = match");
|
||||
// TODO test inverse.
|
||||
|
||||
a = Att ("name", "isnt", "value");
|
||||
f.clear ();
|
||||
f.push_back (a);
|
||||
test.notok (f.pass (mods), "name:value -> name.isnt:value = no match");
|
||||
// TODO test inverse.
|
||||
|
||||
a = Att ("name", "startswith", "val");
|
||||
f.clear ();
|
||||
f.push_back (a);
|
||||
test.ok (f.pass (mods), "name:value -> name.startswith:val = match");
|
||||
// TODO test inverse.
|
||||
|
||||
a = Att ("name", "endswith", "lue");
|
||||
f.clear ();
|
||||
f.push_back (a);
|
||||
test.ok (f.pass (mods), "name:value -> name.endswith:lue = match");
|
||||
// TODO test inverse.
|
||||
|
||||
a = Att ("name", "has", "alu");
|
||||
f.clear ();
|
||||
f.push_back (a);
|
||||
test.ok (f.pass (mods), "name:value -> name.has:alu = match");
|
||||
// TODO test inverse.
|
||||
|
||||
a = Att ("name", "hasnt", "alu");
|
||||
f.clear ();
|
||||
f.push_back (a);
|
||||
test.notok (f.pass (mods), "name:value -> name.hasnt:alu = no match");
|
||||
// TODO test inverse.
|
||||
|
||||
a = Att ("name", "any", "");
|
||||
f.clear ();
|
||||
f.push_back (a);
|
||||
test.ok (f.pass (mods), "name:value -> name.any: = match");
|
||||
// TODO test inverse.
|
||||
|
||||
a = Att ("name", "none", "");
|
||||
f.clear ();
|
||||
f.push_back (a);
|
||||
test.notok (f.pass (mods), "name:value -> name.none: = no match");
|
||||
// TODO test inverse.
|
||||
|
||||
/*
|
||||
"before"
|
||||
"after"
|
||||
"under"
|
||||
"over"
|
||||
"above"
|
||||
"below"
|
||||
*/
|
||||
|
||||
a = Att ("description", "word", "hello");
|
||||
f.clear ();
|
||||
f.push_back (a);
|
||||
test.ok (f.pass (mods), "description:hello, world. -> description.word:hello = match");
|
||||
// TODO test inverse.
|
||||
|
||||
a = Att ("description", "word", "world");
|
||||
f.clear ();
|
||||
f.push_back (a);
|
||||
test.ok (f.pass (mods), "description:hello, world. -> description.word:world = match");
|
||||
// TODO test inverse.
|
||||
|
||||
a = Att ("description", "word", "pig");
|
||||
f.clear ();
|
||||
f.push_back (a);
|
||||
test.notok (f.pass (mods), "description:hello, world. -> description.word:pig = no match");
|
||||
// TODO test inverse.
|
||||
|
||||
a = Att ("description", "noword", "hello");
|
||||
f.clear ();
|
||||
f.push_back (a);
|
||||
test.notok (f.pass (mods), "description:hello, world. -> description.noword:hello = no match");
|
||||
// TODO test inverse.
|
||||
|
||||
a = Att ("description", "noword", "world");
|
||||
f.clear ();
|
||||
f.push_back (a);
|
||||
test.notok (f.pass (mods), "description:hello, world. -> description.noword:world = no match");
|
||||
// TODO test inverse.
|
||||
|
||||
a = Att ("description", "noword", "pig");
|
||||
f.clear ();
|
||||
f.push_back (a);
|
||||
test.ok (f.pass (mods), "description:hello, world. -> description.noword:pig = match");
|
||||
// TODO test inverse.
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
@@ -25,7 +25,7 @@
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
#include <Context.h>
|
||||
#include <rx.h>
|
||||
#include <RegX.h>
|
||||
#include <test.h>
|
||||
|
||||
Context context;
|
||||
@@ -36,30 +36,41 @@ int main (int argc, char** argv)
|
||||
|
||||
std::string text = "This is a test.";
|
||||
|
||||
ut.ok (regexMatch (text, "i. ", true), text + " =~ /i. /");
|
||||
RegX r1 ("i. ", true);
|
||||
ut.ok (r1.match (text), text + " =~ /i. /");
|
||||
|
||||
std::vector <std::string> matches;
|
||||
ut.ok (regexMatch (matches, text, "(i.) ", false), text + " =~ /(i.) /");
|
||||
RegX r2 ("(i.) ", false);
|
||||
ut.ok (r2.match (matches, text), text + " =~ /(i.) /");
|
||||
ut.ok (matches.size () == 1, "1 match");
|
||||
ut.is (matches[0], "is", "$1 == is");
|
||||
|
||||
text = "abcdefghijklmnopqrstuvwxyz";
|
||||
|
||||
ut.ok (regexMatch (text, "t..", true), "t..");
|
||||
ut.ok (regexMatch (text, "T..", false), "T..");
|
||||
ut.ok (!regexMatch (text, "T..", true), "! T..");
|
||||
RegX r3 ("t..", true);
|
||||
ut.ok (r3.match (text), "t..");
|
||||
|
||||
RegX r4 ("T..", false);
|
||||
ut.ok (r4.match (text), "T..");
|
||||
|
||||
RegX r5 ("T..", true);
|
||||
ut.ok (!r5.match (text), "! T..");
|
||||
|
||||
text = "this is a test of the regex engine.";
|
||||
// |...:....|....:....|....:....|....:
|
||||
|
||||
ut.ok (regexMatch (text, "^this"), "^this matches");
|
||||
ut.ok (regexMatch (text, "engine\\.$"), "engine\\.$ matches");
|
||||
RegX r6 ("^this");
|
||||
ut.ok (r6.match (text), "^this matches");
|
||||
|
||||
RegX r7 ("engine\\.$");
|
||||
ut.ok (r7.match (text), "engine\\.$ matches");
|
||||
|
||||
std::vector <std::string> results;
|
||||
std::vector <int> start;
|
||||
std::vector <int> end;
|
||||
ut.ok (regexMatch (results, text, "(e..)", true), "(e..) there are matches");
|
||||
ut.ok (regexMatch (start, end, text, "(e..)", true), "(e..) there are matches");
|
||||
RegX r8 ("(e..)", true);
|
||||
ut.ok (r8.match (results, text), "(e..) there are matches");
|
||||
ut.ok (r8.match (start, end, text), "(e..) there are matches");
|
||||
ut.is (results.size (), (size_t) 1, "(e..) == 1 match");
|
||||
ut.is (results[0], "est", "(e..)[0] == 'est'");
|
||||
ut.is (start[0], 11, "(e..)[0] == 11->");
|
||||
|
||||
137
test/seq.t.cpp
137
test/seq.t.cpp
@@ -1,137 +0,0 @@
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// taskwarrior - a command line task list manager.
|
||||
//
|
||||
// Copyright 2006 - 2011, Paul Beckingham, Federico Hernandez.
|
||||
// All rights reserved.
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or modify it under
|
||||
// the terms of the GNU General Public License as published by the Free Software
|
||||
// Foundation; either version 2 of the License, or (at your option) any later
|
||||
// version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
// FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
||||
// details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License along with
|
||||
// this program; if not, write to the
|
||||
//
|
||||
// Free Software Foundation, Inc.,
|
||||
// 51 Franklin Street, Fifth Floor,
|
||||
// Boston, MA
|
||||
// 02110-1301
|
||||
// USA
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
#include <iostream>
|
||||
#include <Context.h>
|
||||
#include <Sequence.h>
|
||||
#include <test.h>
|
||||
|
||||
Context context;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
Sequence parseSequence (const std::string& input)
|
||||
{
|
||||
try { Sequence s (input); return s; }
|
||||
catch (...) {}
|
||||
return Sequence ();
|
||||
}
|
||||
|
||||
int main (int argc, char** argv)
|
||||
{
|
||||
UnitTest t (30);
|
||||
|
||||
// Test for validity.
|
||||
Sequence seq;
|
||||
t.notok (seq.valid ("1--2"), "not valid 1--2");
|
||||
t.notok (seq.valid ("1-2-3"), "not valid 1-2-3");
|
||||
t.notok (seq.valid ("-1-2"), "not valid -1-2");
|
||||
t.notok (seq.valid ("1-two"), "not valid 1-two");
|
||||
t.notok (seq.valid ("one-2"), "not valid one-2");
|
||||
|
||||
t.ok (seq.valid ("1"), "valid 1");
|
||||
t.ok (seq.valid ("1,3"), "valid 1,3");
|
||||
t.ok (seq.valid ("3,1"), "valid 3,1");
|
||||
t.ok (seq.valid ("1,3-5,7"), "valid 1,3-5,7");
|
||||
t.ok (seq.valid ("1-1000"), "valid 1-1000");
|
||||
t.ok (seq.valid ("1-1001"), "valid 1-1001");
|
||||
t.ok (seq.valid ("1-5,3-7"), "valid 1-5,3-7");
|
||||
|
||||
// 1
|
||||
seq = parseSequence ("1");
|
||||
t.is (seq.size (), (size_t)1, "seq '1' -> 1 item");
|
||||
if (seq.size () == 1)
|
||||
{
|
||||
t.is (seq[0], 1, "seq '1' -> [0] == 1");
|
||||
}
|
||||
else
|
||||
{
|
||||
t.fail ("seq '1' -> [0] == 1");
|
||||
}
|
||||
|
||||
// 1,3
|
||||
seq = parseSequence ("1,3");
|
||||
t.is (seq.size (), (size_t)2, "seq '1,3' -> 2 items");
|
||||
if (seq.size () == 2)
|
||||
{
|
||||
t.is (seq[0], 1, "seq '1,3' -> [0] == 1");
|
||||
t.is (seq[1], 3, "seq '1,3' -> [1] == 3");
|
||||
}
|
||||
else
|
||||
{
|
||||
t.fail ("seq '1,3' -> [0] == 1");
|
||||
t.fail ("seq '1,3' -> [1] == 3");
|
||||
}
|
||||
|
||||
// 1,3-5,7
|
||||
seq = parseSequence ("1,3-5,7");
|
||||
t.is (seq.size (), (size_t)5, "seq '1,3-5,7' -> 5 items");
|
||||
if (seq.size () == 5)
|
||||
{
|
||||
t.is (seq[0], 1, "seq '1,3-5,7' -> [0] == 1");
|
||||
t.is (seq[1], 3, "seq '1,3-5,7' -> [1] == 3");
|
||||
t.is (seq[2], 4, "seq '1,3-5,7' -> [2] == 4");
|
||||
t.is (seq[3], 5, "seq '1,3-5,7' -> [3] == 5");
|
||||
t.is (seq[4], 7, "seq '1,3-5,7' -> [4] == 7");
|
||||
}
|
||||
else
|
||||
{
|
||||
t.fail ("seq '1,3-5,7' -> [0] == 1");
|
||||
t.fail ("seq '1,3-5,7' -> [1] == 3");
|
||||
t.fail ("seq '1,3-5,7' -> [2] == 4");
|
||||
t.fail ("seq '1,3-5,7' -> [3] == 5");
|
||||
t.fail ("seq '1,3-5,7' -> [4] == 7");
|
||||
}
|
||||
|
||||
// 1--2
|
||||
seq = parseSequence ("1--2");
|
||||
t.is (seq.size (), (size_t)0, "seq '1--2' -> 0 items (error)");
|
||||
|
||||
// 1-1000 (SEQUENCE_MAX);
|
||||
seq = parseSequence ("1-1000");
|
||||
t.is (seq.size (), (size_t)1000, "seq '1-1000' -> 1000 items");
|
||||
if (seq.size () == 1000)
|
||||
{
|
||||
t.is (seq[0], 1, "seq '1-1000' -> [0] == 1");
|
||||
t.is (seq[1], 2, "seq '1-1000' -> [1] == 3");
|
||||
t.is (seq[998], 999, "seq '1-1000' -> [998] == 999");
|
||||
t.is (seq[999], 1000, "seq '1-1000' -> [999] == 1000");
|
||||
}
|
||||
else
|
||||
{
|
||||
t.fail ("seq '1-1000' -> [0] == 1");
|
||||
t.fail ("seq '1-1000' -> [1] == 2");
|
||||
t.fail ("seq '1-1000' -> [998] == 999");
|
||||
t.fail ("seq '1-1000' -> [999] == 1000");
|
||||
}
|
||||
|
||||
// 1-1001
|
||||
seq = parseSequence ("1-1001");
|
||||
t.is (seq.size (), (size_t)0, "seq '1-1001' -> 0 items (error)");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
@@ -38,9 +38,8 @@ void get (std::vector <Task>& pending, std::vector <Task>& completed)
|
||||
TDB tdb;
|
||||
tdb.location (".");
|
||||
tdb.lock ();
|
||||
Filter filter;
|
||||
tdb.loadPending (pending, filter);
|
||||
tdb.loadCompleted (completed, filter);
|
||||
tdb.loadPending (pending);
|
||||
tdb.loadCompleted (completed);
|
||||
tdb.unlock ();
|
||||
}
|
||||
|
||||
@@ -60,7 +59,6 @@ int main (int argc, char** argv)
|
||||
context.config.set ("gc", "on");
|
||||
|
||||
// Try reading an empty database.
|
||||
Filter filter;
|
||||
std::vector <Task> all;
|
||||
std::vector <Task> pending;
|
||||
std::vector <Task> completed;
|
||||
@@ -100,7 +98,7 @@ int main (int argc, char** argv)
|
||||
completed.clear ();
|
||||
|
||||
tdb.lock ();
|
||||
tdb.load (all, filter);
|
||||
tdb.load (all);
|
||||
all[0].set ("name", "value2");
|
||||
tdb.update (all[0]); // P1 C0 N0 M1
|
||||
tdb.commit (); // P1 C0 N0 M0
|
||||
@@ -118,7 +116,7 @@ int main (int argc, char** argv)
|
||||
all.clear ();
|
||||
|
||||
tdb.lock ();
|
||||
tdb.loadPending (all, filter);
|
||||
tdb.loadPending (all);
|
||||
all[0].setStatus (Task::completed);
|
||||
tdb.update (all[0]); // P1 C0 N0 M1
|
||||
Task t2 ("[foo:\"bar\" status:\"pending\"]");
|
||||
|
||||
@@ -38,9 +38,8 @@ void get (std::vector <Task>& pending, std::vector <Task>& completed)
|
||||
TDB tdb;
|
||||
tdb.location (".");
|
||||
tdb.lock ();
|
||||
Filter filter;
|
||||
tdb.loadPending (pending, filter);
|
||||
tdb.loadCompleted (completed, filter);
|
||||
tdb.loadPending (pending);
|
||||
tdb.loadCompleted (completed);
|
||||
tdb.unlock ();
|
||||
}
|
||||
|
||||
|
||||
@@ -38,6 +38,7 @@ int main (int argc, char** argv)
|
||||
|
||||
try
|
||||
{
|
||||
/*
|
||||
Variant v = Variant (1) + Variant (2);
|
||||
t.ok (v.type () == Variant::v_integer, "1 + 2 --> integer");
|
||||
t.ok (v.format () == "3", "1 + 2 --> 3");
|
||||
@@ -49,6 +50,7 @@ int main (int argc, char** argv)
|
||||
v = Variant (1.2) + Variant (2);
|
||||
t.ok (v.type () == Variant::v_double, "1.2 + 2 --> double");
|
||||
t.ok (v.format () == "3.2", "1.2 + 2 --> 3.2");
|
||||
*/
|
||||
}
|
||||
|
||||
catch (std::string& e)
|
||||
|
||||
Reference in New Issue
Block a user