From f245fa808c3b28052e294efa728497d46f4dd08e Mon Sep 17 00:00:00 2001 From: Paul Beckingham Date: Sat, 3 Sep 2011 13:17:03 -0400 Subject: [PATCH] Code Cleanup - Removed obsolete TDB, Att and Location code. - Removed associated unit tests, unfortunately all ones that pass. --- src/Att.cpp | 701 -------------------------------------------- src/Att.h | 87 ------ src/CMakeLists.txt | 3 - src/Location.cpp | 73 ----- src/Location.h | 51 ---- src/TDB.cpp | 693 ------------------------------------------- src/TDB.h | 98 ------- test/.gitignore | 2 - test/CMakeLists.txt | 2 +- test/att.t.cpp | 381 ------------------------ test/t2.t.cpp | 1 - 11 files changed, 1 insertion(+), 2091 deletions(-) delete mode 100644 src/Att.cpp delete mode 100644 src/Att.h delete mode 100644 src/Location.cpp delete mode 100644 src/Location.h delete mode 100644 src/TDB.cpp delete mode 100644 src/TDB.h delete mode 100644 test/att.t.cpp diff --git a/src/Att.cpp b/src/Att.cpp deleted file mode 100644 index 73ff24323..000000000 --- a/src/Att.cpp +++ /dev/null @@ -1,701 +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 -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -extern Context context; - -static const char* internalNames[] = -{ - "entry", - "start", - "end", - "parent", - "uuid", - "mask", - "imask", - "limit", - "status", - "description", - "tags", - "urgency", - // Note that annotations are not listed. -}; - -static const char* modifiableNames[] = -{ - "project", - "priority", - "fg", - "bg", - "due", - "recur", - "until", - "wait", - "depends", -}; - -// Synonyms on the same line. -static const char* modifierNames[] = -{ - "before", "under", "below", - "after", "over", "above", - "none", - "any", - "is", "equals", - "isnt", "not", - "has", "contains", - "hasnt", - "startswith", "left", - "endswith", "right", - "word", - "noword" -}; - -#define NUM_INTERNAL_NAMES (sizeof (internalNames) / sizeof (internalNames[0])) -#define NUM_MODIFIABLE_NAMES (sizeof (modifiableNames) / sizeof (modifiableNames[0])) -#define NUM_MODIFIER_NAMES (sizeof (modifierNames) / sizeof (modifierNames[0])) - -//////////////////////////////////////////////////////////////////////////////// -Att::Att () -: _name ("") -, _value ("") -, _mod ("") -, _sense ("positive") -{ -} - -//////////////////////////////////////////////////////////////////////////////// -Att::Att (const std::string& name, const std::string& mod, const std::string& value) -{ - _name = name; - _value = value; - _mod = mod; - _sense = "positive"; -} - -//////////////////////////////////////////////////////////////////////////////// -Att::Att (const std::string& name, const std::string& mod, const std::string& value, - const std::string& sense) -{ - _name = name; - _value = value; - _mod = mod; - _sense = sense; -} - -//////////////////////////////////////////////////////////////////////////////// -Att::Att (const std::string& name, const std::string& mod, int value) -{ - _name = name; - - std::stringstream s; - s << value; - _value = s.str (); - - _mod = mod; - _sense = "positive"; -} - -//////////////////////////////////////////////////////////////////////////////// -Att::Att (const std::string& name, const std::string& value) -{ - _name = name; - _value = value; - _mod = ""; - _sense = "positive"; -} - -//////////////////////////////////////////////////////////////////////////////// -Att::Att (const std::string& name, int value) -{ - _name = name; - - std::stringstream s; - s << value; - _value = s.str (); - - _mod = ""; - _sense = "positive"; -} - -//////////////////////////////////////////////////////////////////////////////// -Att::Att (const Att& other) -{ - _name = other._name; - _value = other._value; - _mod = other._mod; - _sense = other._sense; -} - -//////////////////////////////////////////////////////////////////////////////// -Att& Att::operator= (const Att& other) -{ - if (this != &other) - { - _name = other._name; - _value = other._value; - _mod = other._mod; - _sense = other._sense; - } - - return *this; -} - -//////////////////////////////////////////////////////////////////////////////// -bool Att::operator== (const Att& other) const -{ - return _name == other._name && - _mod == other._mod && - _value == other._value && - _sense == other._sense; -} - -//////////////////////////////////////////////////////////////////////////////// -Att::~Att () -{ -} - -//////////////////////////////////////////////////////////////////////////////// -bool Att::logicSense (bool match) const -{ - if (_sense == "positive") - return match; - else if (_sense == "negative") - return ! match; - else - { - context.debug ("_sense: " + _sense); - throw ("unknown _sense " + _sense); - } -} - -//////////////////////////////////////////////////////////////////////////////// -// For parsing. -bool Att::valid (const std::string& input) const -{ - Nibbler n (input); - std::string ignored; - if (n.getUntilOneOf (".:", ignored)) - { - if (ignored.length () == 0) - return false; - - while (n.skip ('.')) - if (!n.getUntilOneOf (".:", ignored)) - return false; - - if (n.skip (':')) - { - if (input.find ('@') <= n.cursor () || - input.find ('/') <= n.cursor ()) - return false; - - if (n.getQuoted ('"', ignored) || - n.getUntil (' ', ignored) || - n.getUntilEOS (ignored) || - n.depleted ()) - return true; - } - } - - return false; -} - -//////////////////////////////////////////////////////////////////////////////// -bool Att::validInternalName (const std::string& name) -{ - for (unsigned int i = 0; i < NUM_INTERNAL_NAMES; ++i) - if (name == internalNames[i]) - return true; - - return false; -} - -//////////////////////////////////////////////////////////////////////////////// -bool Att::validModifiableName (const std::string& name) -{ - for (unsigned int i = 0; i < NUM_MODIFIABLE_NAMES; ++i) - if (name == modifiableNames[i]) - return true; - - return false; -} - -//////////////////////////////////////////////////////////////////////////////// -bool Att::validNameValue ( - const std::string& name, - const std::string& mod, - const std::string& value) -{ - std::string writableName = name; - std::string writableMod = mod; - std::string writableValue = value; - return Att::validNameValue (writableName, writableMod, writableValue); -} - -//////////////////////////////////////////////////////////////////////////////// -bool Att::validNameValue ( - std::string& name, - std::string& mod, - std::string& value) -{ - // First, guess at the full attribute name. - std::vector candidates; - for (unsigned i = 0; i < NUM_INTERNAL_NAMES; ++i) - candidates.push_back (internalNames[i]); - - for (unsigned i = 0; i < NUM_MODIFIABLE_NAMES; ++i) - candidates.push_back (modifiableNames[i]); - - std::vector matches; - autoComplete (name, - candidates, - matches, - context.config.getInteger ("abbreviation.minimum")); - - if (matches.size () == 0) - return false; - - else if (matches.size () != 1) - { - std::string error = "Ambiguous attribute '" + name + "' - could be either of "; // TODO i18n - - std::sort (matches.begin (), matches.end ()); - std::string combined; - join (combined, ", ", matches); - - throw error + combined + "."; - } - - name = matches[0]; - - // Second, guess at the modifier name. - if (mod != "") - { - candidates.clear (); - for (unsigned i = 0; i < NUM_MODIFIER_NAMES; ++i) - candidates.push_back (modifierNames[i]); - - matches.clear (); - autoComplete (mod, - candidates, - matches, - context.config.getInteger ("abbreviation.minimum")); - - if (matches.size () == 0) - throw std::string ("Unrecognized modifier '") + mod + "'."; - - else if (matches.size () != 1) - { - std::string error = "Ambiguous modifier '" + mod + "' - could be either of "; // TODO i18n - - std::sort (matches.begin (), matches.end ()); - std::string combined; - join (combined, ", ", matches); - error += combined; - - throw error + combined + "."; - } - - mod = matches[0]; - } - - // Some attributes are intended to be private, unless the command is read- - // only, in which cased these are perfectly valid elements of a filter. -/* - if (context.cmd.isWriteCommand () && - !validModifiableName (name)) - throw std::string ("\"") + - name + - "\" is not an attribute you may modify directly."; -*/ - else if (name == "priority") - { - if (value != "") - { - value = upperCase (value); - if (value != "H" && - value != "M" && - value != "L") - throw std::string ("\"") + - value + - "\" is not a valid priority. Use H, M, L or leave blank."; - } - } - - else if (name == "description") - { -// if (context.cmd.isWriteCommand ()) - { - if (value == "") - throw std::string ("The '") + name + "' attribute must not be blank."; - - if (!noVerticalSpace (value)) - throw std::string ("The '") + name + "' attribute must not contain vertical white space."; - } - } - - else if (name == "fg" || name == "bg") - { - // TODO Determine whether color abbreviations are supported, and if so, - // modify 'value' here accordingly. - } - - // Dates can now be either a date, or a duration that is added as an offset - // to the current date. - else if (name == "due" || - name == "until" || - name == "wait") - { - // Validate and convert to epoch. - if (value != "") - { - // Try parsing as a duration. If unsuccessful, try again, as a date. - try - { - Date now; - Duration dur (value); - - if (dur.negative ()) - value = (now - (time_t)dur).toEpochString (); - else - value = (now + (time_t)dur).toEpochString (); - } - - // If the date parsing failed, try parsing as a duration. If successful, - // add the duration to the current date. If unsuccessful, propagate the - // original date parse error. - - // Try parsing as a date. If unsuccessfull, throw. - catch (...) - { - try - { - value = Date (value, context.config.get ("dateformat")).toEpochString (); - } - - catch (std::string& e) - { - throw e; - } - } - } - } - - else if (name == "recur") - { - // Just validate, don't convert to days. - Duration d; - if (value != "") - d.parse (value); - } - - else if (name == "limit") - { - if (value == "" || (value != "page" && !digitsOnly (value))) - throw std::string ("The '") + name + "' attribute must be an integer, or the value 'page'."; - } - - else if (name == "status") - { - value = lowerCase (value); - - std::vector matches; - std::vector candidates; - candidates.push_back ("pending"); - candidates.push_back ("completed"); - candidates.push_back ("deleted"); - candidates.push_back ("recurring"); - candidates.push_back ("waiting"); - autoComplete (value, - candidates, - matches, - context.config.getInteger ("abbreviation.minimum")); - - if (matches.size () == 1) - value = matches[0]; - else - throw std::string ("\"") + - value + - "\" is not a valid status. Use 'pending', 'completed', 'deleted', 'recurring' or 'waiting'."; - } - - else if (! validInternalName (name) && - ! validModifiableName (name)) - throw std::string ("'") + name + "' is not a recognized attribute."; - - return true; -} - -//////////////////////////////////////////////////////////////////////////////// -// TODO Deprecated - remove. -bool Att::validMod (const std::string& mod) -{ - for (unsigned int i = 0; i < NUM_MODIFIER_NAMES; ++i) - if (modifierNames[i] == mod) - return true; - - return false; -} - -//////////////////////////////////////////////////////////////////////////////// -// The type of an attribute is useful for modifier evaluation. -std::string Att::type (const std::string& name) const -{ - if (name == "due" || - name == "wait" || - name == "until" || - name == "start" || - name == "entry" || - name == "end") - return "date"; - - else if (name == "recur") - return "duration"; - - else if (name == "limit" || - name == "urgency") - return "number"; - - else if (name == "priority") - return "priority"; - - else - return "text"; -} - -//////////////////////////////////////////////////////////////////////////////// -// ______________ -// | | -// | v -// start --> name --> . --> mod --> : --> " --> value --> " --> end -// | ^ | ^ -// |_____________________| |_____________| -// -void Att::parse (const std::string& input) -{ - Nibbler n (input); - parse (n); -} - -void Att::parse (Nibbler& n) -{ - // Ensure a clean object first. - _name = ""; - _value = ""; - _mod = ""; - _sense = "positive"; - - if (n.getUntilOneOf (".:", _name)) - { - if (_name.length () == 0) - throw std::string ("Missing attribute name"); // TODO i18n - - if (n.skip ('.')) - { - std::string mod; - - if (n.skip ('~')) - { - context.debug ("using negative logic"); - _sense = "negative"; - } - - if (n.getUntil (":", mod)) - { - if (validMod (mod)) - _mod = mod; - else - throw std::string ("The name '") + mod + "' is not a valid modifier."; // TODO i18n - } - else - throw std::string ("Missing . or : after modifier."); // TODO i18n - } - - if (n.skip (':')) - { - // Both quoted and unquoted Att's are accepted. - // Consider removing this for a stricter parse. - if (n.getQuoted ('"', _value) || - n.getUntilEOS (_value)) - { - decode (_value); - } - } - else - throw std::string ("Missing : after attribute name."); // TODO i18n - } - else - throw std::string ("Missing : after attribute name."); // TODO i18n - -/* TODO This might be too slow to include. Test this assumption. - validNameValue (_name, _mod, _value); -*/ -} - -//////////////////////////////////////////////////////////////////////////////// -// name : " value " -std::string Att::composeF4 () const -{ - std::string output = ""; - - if (_name != "" && _value != "") - { - std::string value = _value; - encode (value); - enquote (value); - - output += _name + ":" + value; - } - - return output; -} - -//////////////////////////////////////////////////////////////////////////////// -void Att::mod (const std::string& input) -{ - if (input != "" && !validMod (input)) - throw std::string ("The name '") + input + "' is not a valid modifier."; // TODO i18n - - _mod = input; -} - -//////////////////////////////////////////////////////////////////////////////// -std::string Att::mod () const -{ - return _mod; -} - -//////////////////////////////////////////////////////////////////////////////// -std::string Att::name () const -{ - return _name; -} - -//////////////////////////////////////////////////////////////////////////////// -void Att::name (const std::string& name) -{ - _name = name; -} - -//////////////////////////////////////////////////////////////////////////////// -std::string Att::value () const -{ - return _value; -} - -//////////////////////////////////////////////////////////////////////////////// -void Att::value (const std::string& value) -{ - _value = value; -} - -//////////////////////////////////////////////////////////////////////////////// -void Att::allNames (std::vector & all) -{ - all.clear (); - - unsigned int i; - for (i = 0; i < NUM_INTERNAL_NAMES; ++i) - all.push_back (internalNames[i]); - - for (i = 0; i < NUM_MODIFIABLE_NAMES; ++i) - all.push_back (modifiableNames[i]); -} - -//////////////////////////////////////////////////////////////////////////////// -// Add quotes. -void Att::enquote (std::string& value) const -{ - value = '"' + value + '"'; -} - -//////////////////////////////////////////////////////////////////////////////// -// Remove quotes. Instead of being picky, just remove them all. There should -// be none within the value, and this will correct for one possible corruption -// that hand-editing the pending.data file could cause. -void Att::dequote (std::string& value) const -{ - str_replace (value, "\"", ""); -} - -//////////////////////////////////////////////////////////////////////////////// -// Encode values prior to serialization. -// \t -> &tab; -// " -> &dquot; -// [ -> &open; -// ] -> &close; -// \ -> \\ (extra chars to disambiguate multi-line comment) -void Att::encode (std::string& value) const -{ - str_replace (value, "\t", "&tab;"); - str_replace (value, "\"", "&dquot;"); - str_replace (value, "[", "&open;"); - str_replace (value, "]", "&close;"); - str_replace (value, "\\", "\\\\"); -} - -//////////////////////////////////////////////////////////////////////////////// -// Decode values after parse. -// \t <- &tab; -// " <- " or &dquot; -// ' <- &squot; -// , <- , -// [ <- &open; -// ] <- &close; -// : <- : -void Att::decode (std::string& value) const -{ - // Supported encodings. - str_replace (value, "&tab;", "\t"); - str_replace (value, "&dquot;", "\""); - str_replace (value, """, "'"); - str_replace (value, "&open;", "["); - str_replace (value, "&close;", "]"); - - // Support for deprecated encodings. These cannot be removed or old files - // will not be parsable. Not just old files - completed.data can contain - // tasks formatted/encoded using these. - str_replace (value, "&squot;", "'"); - str_replace (value, ",", ","); - str_replace (value, ":", ":"); -} - -//////////////////////////////////////////////////////////////////////////////// diff --git a/src/Att.h b/src/Att.h deleted file mode 100644 index 592c7dfd4..000000000 --- a/src/Att.h +++ /dev/null @@ -1,87 +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 -// -//////////////////////////////////////////////////////////////////////////////// -#ifndef INCLUDED_ATT -#define INCLUDED_ATT -#define L10N // Localization complete. - -#include -#include -#include - -class Att -{ -public: - Att (); - Att (const std::string&, const std::string&, const std::string&); - Att (const std::string&, const std::string&, const std::string&, const std::string&); - Att (const std::string&, const std::string&, int); - Att (const std::string&, const std::string&); - Att (const std::string&, int); - Att (const Att&); - Att& operator= (const Att&); - bool operator== (const Att&) const; - ~Att (); - - bool logicSense (bool match) const; - bool valid (const std::string&) const; - static bool validInternalName (const std::string&); - static bool validModifiableName (const std::string&); - static bool validNameValue (const std::string&, const std::string&, const std::string&); - static bool validNameValue (std::string&, std::string&, std::string&); - static bool validMod (const std::string&); - std::string type (const std::string&) const; - void parse (const std::string&); - void parse (Nibbler&); - - std::string composeF4 () const; - - void mod (const std::string&); - std::string mod () const; - - std::string name () const; - void name (const std::string&); - - std::string value () const; - void value (const std::string&); - - static void allNames (std::vector &); - -private: - void enquote (std::string&) const; - void dequote (std::string&) const; - void encode (std::string&) const; - void decode (std::string&) const; - -private: - std::string _name; - std::string _value; - std::string _mod; - std::string _sense; -}; - -#endif -//////////////////////////////////////////////////////////////////////////////// diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 0e3c2ac95..35425aa0e 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -8,7 +8,6 @@ include_directories (${CMAKE_SOURCE_DIR} set (task_SRCS A3.cpp A3.h API.cpp API.h Arg.cpp Arg.h - Att.cpp Att.h Color.cpp Color.h Config.cpp Config.h Context.cpp Context.h @@ -20,12 +19,10 @@ set (task_SRCS A3.cpp A3.h File.cpp File.h Hooks.cpp Hooks.h JSON.cpp JSON.h - Location.cpp Location.h Nibbler.cpp Nibbler.h Path.cpp Path.h Permission.cpp Permission.h RX.cpp RX.h - TDB.cpp TDB.h TDB2.cpp TDB2.h Task.cpp Task.h Taskmod.cpp Taskmod.h diff --git a/src/Location.cpp b/src/Location.cpp deleted file mode 100644 index afc06c916..000000000 --- a/src/Location.cpp +++ /dev/null @@ -1,73 +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 - -//////////////////////////////////////////////////////////////////////////////// -Location::Location () -: _path ("") -, _pending (NULL) -, _completed (NULL) -, _undo (NULL) -{ -} - -//////////////////////////////////////////////////////////////////////////////// -Location::Location (const std::string& p) -: _path (p) -{ -} - -//////////////////////////////////////////////////////////////////////////////// -Location::Location (const Location& other) -{ - _path = other._path; - _pending = other._pending; - _completed = other._completed; - _undo = other._undo; -} - -//////////////////////////////////////////////////////////////////////////////// -Location& Location::operator= (const Location& other) -{ - if (this != &other) - { - _path = other._path; - _pending = other._pending; - _completed = other._completed; - _undo = other._undo; - } - - return *this; -} - -//////////////////////////////////////////////////////////////////////////////// -Location::~Location () -{ -} - -//////////////////////////////////////////////////////////////////////////////// diff --git a/src/Location.h b/src/Location.h deleted file mode 100644 index 41c03e2ae..000000000 --- a/src/Location.h +++ /dev/null @@ -1,51 +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 -// -//////////////////////////////////////////////////////////////////////////////// -#ifndef INCLUDED_LOCATION -#define INCLUDED_LOCATION -#define L10N // Localization complete. - -#include -#include - -class Location -{ -public: - Location (); // Default constructor - Location (const std::string&); // Default constructor - Location (const Location&); // Copy constructor - Location& operator= (const Location&); // Assignment operator - ~Location (); // Destructor - -public: - std::string _path; - FILE* _pending; - FILE* _completed; - FILE* _undo; -}; - -#endif -//////////////////////////////////////////////////////////////////////////////// diff --git a/src/TDB.cpp b/src/TDB.cpp deleted file mode 100644 index d4a4aacd4..000000000 --- a/src/TDB.cpp +++ /dev/null @@ -1,693 +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 -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -extern Context context; - -//////////////////////////////////////////////////////////////////////////////// -// The ctor/dtor do nothing. -// The lock/unlock methods hold the file open. -// There should be only one commit. -// -// +- TDB::TDB -// | -// | +- TDB::lock -// | | open -// | | [lock] -// | | -// | | +- TDB::load -// | | | read all -// | | | return subset -// | | | -// | | +- TDB::add (T) -// | | | -// | | +- TDB::update (T) -// | | | -// | | +- TDB::commit -// | | | write all -// | | | -// | | +- TDB::undo -// | | -// | +- TDB::unlock -// | [unlock] -// | close -// | -// +- TDB::~TDB -// [TDB::unlock] -// -TDB::TDB () -: _lock (true) -, _all_opened_and_locked (false) -, _id (1) -{ -} - -//////////////////////////////////////////////////////////////////////////////// -TDB::~TDB () -{ - if (_all_opened_and_locked) - unlock (); -} - -//////////////////////////////////////////////////////////////////////////////// -void TDB::clear () -{ - _locations.clear (); - _lock = true; - - if (_all_opened_and_locked) - unlock (); - - _all_opened_and_locked = false; - _id = 1; - _pending.clear (); - _new.clear (); - _completed.clear (); - _modified.clear (); -} - -//////////////////////////////////////////////////////////////////////////////// -void TDB::location (const std::string& path) -{ - Directory d (path); - if (!d.exists ()) - throw std::string ("Data location '") + - path + - "' does not exist, or is not readable and writable."; - - _locations.push_back (Location (d)); -} - -//////////////////////////////////////////////////////////////////////////////// -void TDB::lock (bool lockFile /* = true */) -{ - _lock = lockFile; - - _pending.clear (); - _new.clear (); - _completed.clear (); - _modified.clear (); - - foreach (location, _locations) - { - location->_pending = openAndLock (location->_path + "/pending.data"); - location->_completed = openAndLock (location->_path + "/completed.data"); - location->_undo = openAndLock (location->_path + "/undo.data"); - } - - _all_opened_and_locked = true; -} - -//////////////////////////////////////////////////////////////////////////////// -void TDB::unlock () -{ - // Do not clear out these items, as they may be used in a read-only fashion. - // _pending.clear (); - // _new.clear (); - // _modified.clear (); - - foreach (location, _locations) - { - fflush (location->_pending); - fclose (location->_pending); - location->_pending = NULL; - - fflush (location->_completed); - fclose (location->_completed); - location->_completed = NULL; - - fflush (location->_undo); - fclose (location->_undo); - location->_completed = NULL; - } - - _all_opened_and_locked = false; -} - -//////////////////////////////////////////////////////////////////////////////// -// Returns number of filtered tasks. -// Note: tasks.clear () is deliberately not called, to allow the combination of -// multiple files. -int TDB::load (std::vector & tasks) -{ - // Special optimization: if the filter contains Att ('status', '', 'pending'), - // and no other 'status' filters, then loadCompleted can be skipped. - int numberStatusClauses = 0; - int numberSimpleStatusClauses = 0; - - loadPending (tasks); - - if (numberStatusClauses == 0 || - numberStatusClauses != numberSimpleStatusClauses) - loadCompleted (tasks); - else - context.debug ("load optimization short circuit"); - - return tasks.size (); -} - -//////////////////////////////////////////////////////////////////////////////// -// Returns number of filtered tasks. -// Note: tasks.clear () is deliberately not called, to allow the combination of -// multiple files. -int TDB::loadPending (std::vector & tasks) -{ - std::string file; - int line_number = 1; - - try - { - // Only load if not already loaded. - if (_pending.size () == 0) - { - _id = 1; - char line[T_LINE_MAX]; - foreach (location, _locations) - { - line_number = 1; - file = location->_path + "/pending.data"; - - fseek (location->_pending, 0, SEEK_SET); - while (fgets (line, T_LINE_MAX, location->_pending)) - { - int length = strlen (line); - if (length > 3) // []\n - { - // TODO Add hidden attribute indicating source? - Task task (line); - task.id = _id++; - - _pending.push_back (task); - - // Maintain mapping for ease of link/dependency resolution. - // Note that this mapping is not restricted by the filter, and is - // therefore a complete set. - _I2U[task.id] = task.get ("uuid"); - _U2I[task.get ("uuid")] = task.id; - } - - ++line_number; - } - } - } - - // Now filter and return. - foreach (task, _pending) - tasks.push_back (*task); - - // Hand back any accumulated additions, if TDB::loadPending is being called - // repeatedly. - int fakeId = _id; - foreach (task, _new) - { - task->id = fakeId++; - tasks.push_back (*task); - } - } - - catch (std::string& e) - { - std::stringstream s; - s << " in " << file << " at line " << line_number; - throw e + s.str (); - } - - return tasks.size (); -} - -//////////////////////////////////////////////////////////////////////////////// -// Returns number of filtered tasks. -// Note: tasks.clear () is deliberately not called, to allow the combination of -// multiple files. -int TDB::loadCompleted (std::vector & tasks) -{ - std::string file; - int line_number = 1; - - try - { - if (_completed.size () == 0) - { - char line[T_LINE_MAX]; - foreach (location, _locations) - { - line_number = 1; - file = location->_path + "/completed.data"; - - fseek (location->_completed, 0, SEEK_SET); - while (fgets (line, T_LINE_MAX, location->_completed)) - { - int length = strlen (line); - if (length > 3) // []\n - { - // TODO Add hidden attribute indicating source? - - Task task (line); - task.id = 0; // Need a value, just not a valid value. - - _completed.push_back (task); - } - - ++line_number; - } - } - } - - // Now filter and return. - foreach (task, _completed) - tasks.push_back (*task); - } - - catch (std::string& e) - { - std::stringstream s; - s << " in " << file << " at line " << line_number; - throw e + s.str (); - } - - return tasks.size (); -} - -//////////////////////////////////////////////////////////////////////////////// -const std::vector & TDB::getAllPending () -{ - return _pending; -} - -//////////////////////////////////////////////////////////////////////////////// -const std::vector & TDB::getAllNew () -{ - return _new; -} - -//////////////////////////////////////////////////////////////////////////////// -const std::vector & TDB::getAllCompleted () -{ - return _completed; -} - -//////////////////////////////////////////////////////////////////////////////// -const std::vector & TDB::getAllModified () -{ - return _modified; -} - -//////////////////////////////////////////////////////////////////////////////// -// Note: _locations[0] is where all tasks are written. -void TDB::add (const Task& task) -{ - std::string unique; - Task t (task); - if (task.get ("uuid") == "") - unique = ::uuid (); - else - unique = task.get ("uuid"); - - t.set ("uuid", unique); - - // If the tasks are loaded, then verify that this uuid is not already in - // the file. - if (uuidAlreadyUsed (unique, _new) || - uuidAlreadyUsed (unique, _modified) || - uuidAlreadyUsed (unique, _pending) || - uuidAlreadyUsed (unique, _completed)) - throw std::string ("Cannot add task because the uuid '") + unique + "' is not unique."; - - _new.push_back (t); - _I2U[task.id] = unique; - _U2I[task.get ("uuid")] = t.id; -} - -//////////////////////////////////////////////////////////////////////////////// -void TDB::update (const Task& task) -{ - _modified.push_back (task); -} - -//////////////////////////////////////////////////////////////////////////////// -// Interestingly, only the pending file gets written to. The completed file is -// only modified by TDB::gc. -int TDB::commit () -{ - context.timer_gc.start (); - - int quantity = _new.size () + _modified.size (); - - // This is an optimization. If there are only new tasks, and none were - // modified, simply seek to the end of pending and write. - if (_new.size () && ! _modified.size ()) - { - fseek (_locations[0]._pending, 0, SEEK_END); - foreach (task, _new) - { - _pending.push_back (*task); - fputs (task->composeF4 ().c_str (), _locations[0]._pending); - } - - fseek (_locations[0]._undo, 0, SEEK_END); - foreach (task, _new) - writeUndo (*task, _locations[0]._undo); - - _new.clear (); - return quantity; - } - - // The alternative is to potentially rewrite both files. - else if (_new.size () || _modified.size ()) - { - // allPending is a copy of _pending, with all modifications included, and - // new tasks appended. - std::vector allPending; - allPending = _pending; - foreach (mtask, _modified) - { - foreach (task, allPending) - { - if (task->id == mtask->id) - { - *task = *mtask; - goto next_mod; - } - } - - next_mod: - ; - } - - foreach (task, _new) - allPending.push_back (*task); - - // Write out all pending. - if (fseek (_locations[0]._pending, 0, SEEK_SET) == 0) - { - if (ftruncate (fileno (_locations[0]._pending), 0)) - throw std::string ("Failed to truncate pending.data file "); - - foreach (task, allPending) - fputs (task->composeF4 ().c_str (), _locations[0]._pending); - } - - // Update the undo log. - if (fseek (_locations[0]._undo, 0, SEEK_END) == 0) - { - foreach (mtask, _modified) - { - foreach (task, _pending) - { - if (task->id == mtask->id) - { - writeUndo (*task, *mtask, _locations[0]._undo); - goto next_mod2; - } - } - - next_mod2: - ; - } - - foreach (task, _new) - writeUndo (*task, _locations[0]._undo); - } - - _pending = allPending; - - _modified.clear (); - _new.clear (); - } - - context.timer_gc.stop (); - return quantity; -} - -//////////////////////////////////////////////////////////////////////////////// -// Scans the pending tasks for any that are completed or deleted, and if so, -// moves them to the completed.data file. Returns a count of tasks moved. -// Now reverts expired waiting tasks to pending. -// Now cleans up dangling dependencies. -int TDB::gc () -{ - context.timer_gc.start (); - - // Allowed as a temporary override. - if (!context.config.getBoolean ("gc")) - { - context.timer_gc.stop (); - return 0; - } - - int count_pending_changes = 0; - int count_completed_changes = 0; - Date now; - - if (_new.size ()) - throw std::string ("Unexpected new tasks found during gc."); - - if (_modified.size ()) - throw std::string ("Unexpected modified tasks found during gc."); - - lock (); - - std::vector ignore; - loadPending (ignore); - - // Search for dangling dependencies. These are dependencies whose uuid cannot - // be converted to an id by TDB. - std::vector deps; - foreach (task, _pending) - { - if (task->has ("depends")) - { - deps.clear (); - task->getDependencies (deps); - foreach (dep, deps) - { - if (id (*dep) == 0) - { - task->removeDependency (*dep); - ++count_pending_changes; - context.debug ("GC: Removed dangling dependency " - + task->get ("uuid") - + " -> " - + *dep); - } - } - } - } - - // Now move completed and deleted tasks from the pending list to the - // completed list. Isn't garbage collection easy? - std::vector still_pending; - std::vector newly_completed; - foreach (task, _pending) - { - Task::status s = task->getStatus (); - if (s == Task::completed || - s == Task::deleted) - { - newly_completed.push_back (*task); - ++count_pending_changes; // removal - ++count_completed_changes; // addition - } - else if (s == Task::waiting) - { - // Wake up tasks that need to be woken. - Date wait_date (task->get_date ("wait")); - if (now > wait_date) - { - task->setStatus (Task::pending); - task->remove ("wait"); - ++count_pending_changes; // modification - - context.debug (std::string ("TDB::gc waiting -> pending for ") + - task->get ("uuid")); - } - - still_pending.push_back (*task); - } - else - still_pending.push_back (*task); - } - - // No commit - all updates performed manually. - if (count_pending_changes > 0) - { - if (fseek (_locations[0]._pending, 0, SEEK_SET) == 0) - { - if (ftruncate (fileno (_locations[0]._pending), 0)) - throw std::string ("Failed to truncate pending.data file "); - - foreach (task, still_pending) - fputs (task->composeF4 ().c_str (), _locations[0]._pending); - - // Update cached copy. - _pending = still_pending; - } - } - - // Append the new_completed tasks to completed.data. No need to write out the - // whole list. - if (count_completed_changes > 0) - { - fseek (_locations[0]._completed, 0, SEEK_END); - foreach (task, newly_completed) - fputs (task->composeF4 ().c_str (), _locations[0]._completed); - } - - // Close files. - unlock (); - - std::stringstream s; - s << "gc " << (count_pending_changes + count_completed_changes) << " tasks"; - context.debug (s.str ()); - - context.timer_gc.stop (); - return count_pending_changes + count_completed_changes; -} - -//////////////////////////////////////////////////////////////////////////////// -int TDB::nextId () -{ - return _id++; -} - -//////////////////////////////////////////////////////////////////////////////// -void TDB::undo () -{ -} - -//////////////////////////////////////////////////////////////////////////////// -void TDB::merge (const std::string& mergeFile) -{ -} - -//////////////////////////////////////////////////////////////////////////////// -std::string TDB::uuid (int id) const -{ - std::map ::const_iterator i; - if ((i = _I2U.find (id)) != _I2U.end ()) - return i->second; - - return ""; -} - -//////////////////////////////////////////////////////////////////////////////// -int TDB::id (const std::string& uuid) const -{ - std::map ::const_iterator i; - if ((i = _U2I.find (uuid)) != _U2I.end ()) - return i->second; - - return 0; -} - -//////////////////////////////////////////////////////////////////////////////// -FILE* TDB::openAndLock (const std::string& file) -{ - // TODO Need provision here for read-only locations. - - // Check for access. - File f (file); - bool exists = f.exists (); - if (exists) - if (!f.readable () || !f.writable ()) - throw std::string ("Task does not have the correct permissions for '") + - file + "'."; - - // Open the file. - FILE* in = fopen (file.c_str (), (exists ? "r+" : "w+")); - if (!in) - throw std::string ("Could not open '") + file + "'."; - - // Lock if desired. Try three times before failing. - if (_lock) - { - int retry = 0; - while (flock (fileno (in), LOCK_NB | LOCK_EX) && ++retry <= 3) - { - std::cout << "Waiting for file lock...\n"; - while (flock (fileno (in), LOCK_NB | LOCK_EX) && ++retry <= 3) - delay (0.2); - } - - if (retry > 3) - throw std::string ("Could not lock '") + file + "'."; - } - - return in; -} - -//////////////////////////////////////////////////////////////////////////////// -void TDB::writeUndo (const Task& after, FILE* file) -{ - fprintf (file, - "time %u\nnew %s---\n", - (unsigned int) time (NULL), - after.composeF4 ().c_str ()); -} - -//////////////////////////////////////////////////////////////////////////////// -void TDB::writeUndo (const Task& before, const Task& after, FILE* file) -{ - fprintf (file, - "time %u\nold %snew %s---\n", - (unsigned int) time (NULL), - before.composeF4 ().c_str (), - after.composeF4 ().c_str ()); -} - -//////////////////////////////////////////////////////////////////////////////// -bool TDB::uuidAlreadyUsed ( - const std::string& uuid, - const std::vector & all) -{ - std::vector ::const_iterator it; - for (it = all.begin (); it != all.end (); ++it) - if (it->get ("uuid") == uuid) - return true; - - return false; -} - -//////////////////////////////////////////////////////////////////////////////// diff --git a/src/TDB.h b/src/TDB.h deleted file mode 100644 index e0948cbda..000000000 --- a/src/TDB.h +++ /dev/null @@ -1,98 +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 -// -//////////////////////////////////////////////////////////////////////////////// -#ifndef INCLUDED_TDB -#define INCLUDED_TDB -#define L10N // Localization complete. - -#include -#include -#include -#include -#include - -// Length of longest line. -#define T_LINE_MAX 32768 - -class TDB -{ -public: - TDB (); // Default constructor - ~TDB (); // Destructor - - TDB (const TDB&); - TDB& operator= (const TDB&); - - void clear (); - void location (const std::string&); - - void lock (bool lockFile = true); - void unlock (); - - int load (std::vector &); - int loadPending (std::vector &); - int loadCompleted (std::vector &); - - const std::vector & getAllPending (); - const std::vector & getAllNew (); - const std::vector & getAllCompleted (); - const std::vector & getAllModified (); - - void add (const Task&); // Single task add to pending - void update (const Task&); // Single task update to pending - int commit (); // Write out all tasks - int gc (); // Clean up pending - int nextId (); - void undo (); - void merge (const std::string&); - - std::string uuid (int) const; - int id (const std::string&) const; - -private: - FILE* openAndLock (const std::string&); - void writeUndo (const Task&, FILE*); - void writeUndo (const Task&, const Task&, FILE*); - bool uuidAlreadyUsed (const std::string&); - bool uuidAlreadyUsed (const std::string&, const std::vector &); - -private: - std::vector _locations; - bool _lock; - bool _all_opened_and_locked; - int _id; - - std::vector _pending; // Contents of pending.data - std::vector _completed; // Contents of pending.data - std::vector _new; // Uncommitted new tasks - std::vector _modified; // Uncommitted modified tasks - - std::map _I2U; // ID -> UUID map - std::map _U2I; // UUID -> ID map -}; - -#endif -//////////////////////////////////////////////////////////////////////////////// diff --git a/test/.gitignore b/test/.gitignore index aca92984b..3bf359b7a 100644 --- a/test/.gitignore +++ b/test/.gitignore @@ -2,7 +2,6 @@ *.data *.log arguments.t -att.t autocomplete.t cmd.t color.t @@ -27,7 +26,6 @@ subst.t t.t t2.t taskmod.t -tdb.t tdb2.t text.t transport.t diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 75a010b2f..383b10826 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -6,7 +6,7 @@ include_directories (${CMAKE_SOURCE_DIR} ${CMAKE_SOURCE_DIR}/test ${TASK_INCLUDE_DIRS}) -set (test_SRCS att.t autocomplete.t color.t config.t date.t directory.t dom.t +set (test_SRCS autocomplete.t color.t config.t date.t directory.t dom.t duration.t file.t i18n.t json.t list.t nibbler.t path.t rx.t t.t t2.t taskmod.t tdb2.t text.t uri.t util.t view.t json_test) diff --git a/test/att.t.cpp b/test/att.t.cpp deleted file mode 100644 index 6428bd755..000000000 --- a/test/att.t.cpp +++ /dev/null @@ -1,381 +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 -#include -#include -#include - -Context context; - -//////////////////////////////////////////////////////////////////////////////// -int main (int argc, char** argv) -{ - UnitTest t (118); - - Att a; - t.notok (a.valid ("name"), "Att::valid name -> fail"); - t.notok (a.valid (":"), "Att::valid : -> fail"); - t.notok (a.valid (":value"), "Att::valid :value -> fail"); - t.notok (a.valid ("n@me.mod:value"), "Att::valie n@me.mod:value -> fail"); - t.notok (a.valid ("n/me.mod:value"), "Att::valie n/me.mod:value -> fail"); - t.notok (a.valid ("name.m@d:value"), "Att::valie name.m@d:value -> fail"); - t.notok (a.valid ("name.m/d:value"), "Att::valie name.m/d:value -> fail"); - - t.ok (a.valid ("name:value"), "Att::valid name:value"); - t.ok (a.valid ("name:value "), "Att::valid name:value\\s"); - t.ok (a.valid ("name:'value'"), "Att::valid name:'value'"); - t.ok (a.valid ("name:'one two'"), "Att::valid name:'one two'"); - t.ok (a.valid ("name:\"value\""), "Att::valid name:\"value\""); - t.ok (a.valid ("name:\"one two\""), "Att::valid name:\"one two\""); - t.ok (a.valid ("name:"), "Att::valid name:"); - t.ok (a.valid ("name:""), "Att::valid ""); - t.ok (a.valid ("name.one:value"), "Att::valid name.one.value"); - t.ok (a.valid ("name.one.two:value"), "Att::valid name.one.two:value"); - t.ok (a.valid ("name.:value"), "Att::valid name.:value"); - t.ok (a.valid ("name..:value"), "Att::valid name..:value"); - - Att a1 ("name", "value"); - t.is (a1.name (), "name", "Att::Att (name, value), Att.name"); - t.is (a1.value (), "value", "Att::Att (name, value), Att.value"); - - Att a2; - a2.name ("name"); - a2.value ("value"); - t.is (a2.name (), "name", "Att::Att (), Att.name"); - t.is (a2.value (), "value", "Att::Att (), Att.value"); - - Att a3 (a2); - t.is (a3.name (), "name", "Att::Att (Att), Att.name"); - t.is (a3.value (), "value", "Att::Att (Att), Att.value"); - - Att a4; - a4 = a2; - t.is (a4.name (), "name", "Att::Att (), Att.operator=, Att.name"); - t.is (a4.value (), "value", "Att::Att (), Att.operator=, Att.value"); - - Att a5 ("name", "value"); - t.is (a5.composeF4 (), "name:\"value\"", "Att::composeF4 simple"); - a5.value ("\""); - t.is (a5.composeF4 (), "name:\"&dquot;\"", "Att::composeF4 encoded \""); - a5.value ("\t\",[]:"); - t.is (a5.composeF4 (), "name:\"&tab;&dquot;,&open;&close;:\"", "Att::composeF4 fully encoded \\t\",[]:"); - - Att a6 ("name", 7); - - // Att::mod - straight comparisons. - bool good = true; - try {a6.mod ("is");} catch (...) {good = false;} - t.ok (good, "Att::mod (is)"); - - good = true; - try {a6.mod ("before");} catch (...) {good = false;} - t.ok (good, "Att::mod (before)"); - - good = true; - try {a6.mod ("after");} catch (...) {good = false;} - t.ok (good, "Att::mod (after)"); - - good = true; - try {a6.mod ("none");} catch (...) {good = false;} - t.ok (good, "Att::mod (none)"); - - good = true; - try {a6.mod ("any");} catch (...) {good = false;} - t.ok (good, "Att::mod (any)"); - - good = true; - try {a6.mod ("over");} catch (...) {good = false;} - t.ok (good, "Att::mod (over)"); - - good = true; - try {a6.mod ("under");} catch (...) {good = false;} - t.ok (good, "Att::mod (under)"); - - good = true; - try {a6.mod ("above");} catch (...) {good = false;} - t.ok (good, "Att::mod (above)"); - - good = true; - try {a6.mod ("below");} catch (...) {good = false;} - t.ok (good, "Att::mod (below)"); - - good = true; - try {a6.mod ("isnt");} catch (...) {good = false;} - t.ok (good, "Att::mod (isnt)"); - - good = true; - try {a6.mod ("has");} catch (...) {good = false;} - t.ok (good, "Att::mod (has)"); - - good = true; - try {a6.mod ("contains");} catch (...) {good = false;} - t.ok (good, "Att::mod (contains)"); - - good = true; - try {a6.mod ("hasnt");} catch (...) {good = false;} - t.ok (good, "Att::mod (hasnt)"); - - good = true; - try {a6.mod ("startswith");} catch (...) {good = false;} - t.ok (good, "Att::mod (startswith)"); - - good = true; - try {a6.mod ("endswith");} catch (...) {good = false;} - t.ok (good, "Att::mod (endswith)"); - - good = true; - try {a6.mod ("word");} catch (...) {good = false;} - t.ok (good, "Att::mod (word)"); - - good = true; - try {a6.mod ("noword");} catch (...) {good = false;} - t.ok (good, "Att::mod (noword)"); - - good = true; - try {a6.mod ("unrecognized");} catch (...) {good = false;} - t.notok (good, "Att::mod (unrecognized)"); - - // Att::mod - regex comparisons. - context.config.set ("regex", "on"); - - good = true; - try {a6.mod ("is");} catch (...) {good = false;} - t.ok (good, "Att::mod (is)"); - - good = true; - try {a6.mod ("before");} catch (...) {good = false;} - t.ok (good, "Att::mod (before)"); - - good = true; - try {a6.mod ("after");} catch (...) {good = false;} - t.ok (good, "Att::mod (after)"); - - good = true; - try {a6.mod ("none");} catch (...) {good = false;} - t.ok (good, "Att::mod (none)"); - - good = true; - try {a6.mod ("any");} catch (...) {good = false;} - t.ok (good, "Att::mod (any)"); - - good = true; - try {a6.mod ("over");} catch (...) {good = false;} - t.ok (good, "Att::mod (over)"); - - good = true; - try {a6.mod ("under");} catch (...) {good = false;} - t.ok (good, "Att::mod (under)"); - - good = true; - try {a6.mod ("above");} catch (...) {good = false;} - t.ok (good, "Att::mod (above)"); - - good = true; - try {a6.mod ("below");} catch (...) {good = false;} - t.ok (good, "Att::mod (below)"); - - good = true; - try {a6.mod ("isnt");} catch (...) {good = false;} - t.ok (good, "Att::mod (isnt)"); - - good = true; - try {a6.mod ("has");} catch (...) {good = false;} - t.ok (good, "Att::mod (has)"); - - good = true; - try {a6.mod ("contains");} catch (...) {good = false;} - t.ok (good, "Att::mod (contains)"); - - good = true; - try {a6.mod ("hasnt");} catch (...) {good = false;} - t.ok (good, "Att::mod (hasnt)"); - - good = true; - try {a6.mod ("startswith");} catch (...) {good = false;} - t.ok (good, "Att::mod (startswith)"); - - good = true; - try {a6.mod ("endswith");} catch (...) {good = false;} - t.ok (good, "Att::mod (endswith)"); - - good = true; - try {a6.mod ("word");} catch (...) {good = false;} - t.ok (good, "Att::mod (word)"); - - good = true; - try {a6.mod ("noword");} catch (...) {good = false;} - t.ok (good, "Att::mod (noword)"); - - good = true; - try {a6.mod ("unrecognized");} catch (...) {good = false;} - t.notok (good, "Att::mod (unrecognized)"); - - // Att::parse - Nibbler n (""); - Att a7; - good = true; - try {a7.parse (n);} catch (...) {good = false;} - t.notok (good, "Att::parse () -> throw"); - - n = Nibbler ("name:value"); - a7.parse (n); - t.is (a7.composeF4 (), "name:\"value\"", - "Att::parse (name:value)"); - - n = Nibbler ("name:\"value\""); - a7.parse (n); - t.is (a7.composeF4 (), "name:\"value\"", - "Att::parse (name:\"value\")"); - - n = Nibbler ("name:\"one two\""); - a7.parse (n); - t.is (a7.composeF4 (), "name:\"one two\"", - "Att::parse (name:\"one two\")"); - - n = Nibbler ("name:\""\""); - a7.parse (n); - t.is (a7.composeF4 (), "name:\"'\"", - "Att::parse (name:\"'\")"); - - n = Nibbler ("name:\"&tab;",&open;&close;:\""); - a7.parse (n); - t.is (a7.composeF4 (), "name:\"&tab;',&open;&close;:\"", - "Att::parse (name:\"&tab;',&open;&close;:\")"); - - n = Nibbler ("total gibberish"); - good = true; - try {a7.parse (n);} catch (...) {good = false;} - t.notok (good, "Att::parse (total gibberish)"); - - n = Nibbler ("malformed"); - good = true; - try {a7.parse (n);} catch (...) {good = false;} - t.notok (good, "Att::parse (malformed)"); - - n = Nibbler (":malformed"); - good = true; - try {a7.parse (n);} catch (...) {good = false;} - t.notok (good, "Att::parse (:malformed)"); - - n = Nibbler (":\"\""); - good = true; - try {a7.parse (n);} catch (...) {good = false;} - t.notok (good, "Att::parse (:\"\")"); - - n = Nibbler (":\""); - good = true; - try {a7.parse (n);} catch (...) {good = false;} - t.notok (good, "Att::parse (:\")"); - - n = Nibbler ("name:"); - good = true; - try {a7.parse (n);} catch (...) {good = false;} - t.ok (good, "Att::parse (name:)"); - - n = Nibbler ("name:\"value"); - good = true; - try {a7.parse (n);} catch (...) {good = false;} - t.ok (good, "Att::parse (name:\"value)"); - t.is (a7.composeF4 (), "name:\"&dquot;value\"", "Att::composeF4 -> name:\"&dquot;value\""); - - n = Nibbler ("name:value\""); - good = true; - try {a7.parse (n);} catch (...) {good = false;} - t.ok (good, "Att::parse (name:value\")"); - t.is (a7.composeF4 (), "name:\"value&dquot;\"", "Att::composeF4 -> name:\"value&dquot;\""); - - n = Nibbler ("name:val\"ue"); - good = true; - try {a7.parse (n);} catch (...) {good = false;} - t.ok (good, "Att::parse (name:val\"ue)"); - t.is (a7.composeF4 (), "name:\"val&dquot;ue\"", "Att::composeF4 -> name:\"val&dquot;ue\""); - - n = Nibbler ("name\""); - good = true; - try {a7.parse (n);} catch (...) {good = false;} - t.notok (good, "Att::parse (name\")"); - - // Mods - n = Nibbler ("name.any:\"value\""); - good = true; - try {a7.parse (n);} catch (...) {good = false;} - t.ok (good, "Att::parse (name.any:\"value\")"); - t.is (a7.composeF4 (), "name:\"value\"", "Att::composeF4 -> name:\"value\""); - - n = Nibbler ("name.bogus:\"value\""); - good = true; - try {a7.parse (n);} catch (...) {good = false;} - t.notok (good, "Att::parse (name.bogus:\"value\")"); - - // Att::type - t.is (a.type ("entry"), "date", "Att::type entry -> date"); - t.is (a.type ("due"), "date", "Att::type due -> date"); - t.is (a.type ("until"), "date", "Att::type until -> date"); - t.is (a.type ("start"), "date", "Att::type start -> date"); - t.is (a.type ("end"), "date", "Att::type end -> date"); - t.is (a.type ("wait"), "date", "Att::type wait -> date"); - t.is (a.type ("recur"), "duration", "Att::type recur -> duration"); - t.is (a.type ("limit"), "number", "Att::type limit -> number"); - t.is (a.type ("description"), "text", "Att::type description -> text"); - t.is (a.type ("foo"), "text", "Att::type foo -> text"); - - // Att::validInternalName - t.ok (Att::validInternalName ("entry"), "internal entry"); - t.ok (Att::validInternalName ("start"), "internal start"); - t.ok (Att::validInternalName ("end"), "internal end"); - t.ok (Att::validInternalName ("parent"), "internal parent"); - t.ok (Att::validInternalName ("uuid"), "internal uuid"); - t.ok (Att::validInternalName ("mask"), "internal mask"); - t.ok (Att::validInternalName ("imask"), "internal imask"); - t.ok (Att::validInternalName ("limit"), "internal limit"); - t.ok (Att::validInternalName ("status"), "internal status"); - t.ok (Att::validInternalName ("description"), "internal description"); - - // Att::validModifiableName - t.ok (Att::validModifiableName ("project"), "modifiable project"); - t.ok (Att::validModifiableName ("priority"), "modifiable priority"); - t.ok (Att::validModifiableName ("fg"), "modifiable fg"); - t.ok (Att::validModifiableName ("bg"), "modifiable bg"); - t.ok (Att::validModifiableName ("due"), "modifiable due"); - t.ok (Att::validModifiableName ("recur"), "modifiable recur"); - t.ok (Att::validModifiableName ("until"), "modifiable until"); - t.ok (Att::validModifiableName ("wait"), "modifiable wait"); - - // Att::allNames - std::vector all; - Att::allNames (all); - - std::vector ::iterator it; - it = std::find (all.begin (), all.end (), "uuid"); - t.ok (it != all.end (), "internal name 'uuid' found in Att::allNames"); - it = std::find (all.begin (), all.end (), "project"); - t.ok (it != all.end (), "modifiable name 'project' found in Att::allNames"); - - return 0; -} - -//////////////////////////////////////////////////////////////////////////////// diff --git a/test/t2.t.cpp b/test/t2.t.cpp index e8292e6ea..c0f43bb8d 100644 --- a/test/t2.t.cpp +++ b/test/t2.t.cpp @@ -26,7 +26,6 @@ //////////////////////////////////////////////////////////////////////////////// #include #include -#include #include #include