From 7a45db4d0fee0cb109616629c9d49cd2d090158a Mon Sep 17 00:00:00 2001 From: Paul Beckingham Date: Sun, 19 Feb 2012 22:27:40 -0500 Subject: [PATCH] Feature #891 - Added feature #891, which allows for leftmost partial matches of UUID values. Makes direct comparisons for full-length values, and regular expressions for partial values. Note that there is a minimum length of 8 hex digits. - Added safety parsing mechanism that fails a partial UUID if immediately followed by a hex digit. This allows for numbers longer than 8 digits to not be misinterpreted as a UUID. - Implemented Nibbler::getPartialUUID. - Implemented unit tests. @@ -1145,12 +1145,23 @@ const A3 A3::sequence (const A3& input) const for (unsigned int i = 0; i < uuids.size (); ++i) { - if (ids.size ()) + if (ids.size () + i > 0) sequenced.push_back (Arg ("or", Arg::cat_op)); - sequenced.push_back (Arg ("uuid", Arg::type_string, Arg::cat_dom)); - sequenced.push_back (Arg ("=", Arg::cat_op)); - sequenced.push_back (Arg (uuids[i], Arg::type_string, Arg::cat_literal)); + // A full-length UUID requires a string comparison. + if (uuids[i].length () == 36) + { + sequenced.push_back (Arg ("uuid", Arg::type_string, Arg::cat_dom)); + sequenced.push_back (Arg ("=", Arg::cat_op)); + sequenced.push_back (Arg (uuids[i], Arg::type_string, Arg::cat_literal)); + } + // A UUID fragment is a leftmost comparison. + else + { + sequenced.push_back (Arg ("uuid", Arg::type_string, Arg::cat_dom)); + sequenced.push_back (Arg ("~", Arg::cat_op)); + sequenced.push_back (Arg ("^" + uuids[i], Arg::type_string, Arg::cat_rx)); + } } sequenced.push_back (Arg (")", Arg::cat_op)); @@ -1674,11 +1685,11 @@ bool A3::is_uuid (Nibbler& n, std::string& result) n.save (); result = ""; std::string uuid; - if (n.getUUID (uuid)) + if (n.getPartialUUID (uuid)) { result += uuid; while (n.skip (',') && - n.getUUID (uuid)) + n.getPartialUUID (uuid)) { result += ',' + uuid; } @@ -1997,13 +2008,13 @@ bool A3::extract_uuid ( Nibbler n (input); std::string uuid; - if (n.getUUID (uuid)) + if (n.getPartialUUID (uuid)) { sequence.push_back (uuid); while (n.skip (',')) { - if (!n.getUUID (uuid)) + if (!n.getPartialUUID (uuid)) throw std::string (STRING_A3_UUID_AFTER_COMMA); sequence.push_back (uuid); --- ChangeLog | 1 + src/A3.cpp | 27 +++++-- src/Nibbler.cpp | 33 +++++++- src/Nibbler.h | 1 + test/feature.891.t | 192 +++++++++++++++++++++++++++++++++++++++++++++ test/nibbler.t.cpp | 159 ++++++++++++++++++++++++++++++++++++- 6 files changed, 400 insertions(+), 13 deletions(-) create mode 100755 test/feature.891.t diff --git a/ChangeLog b/ChangeLog index ca325e5a7..1e1722d66 100644 --- a/ChangeLog +++ b/ChangeLog @@ -115,6 +115,7 @@ + Added feature #827, which allows augmentation of default.command with extra arguments, when default.command itself contains mulitple arguments (thanks to Aikido Guy). + + Added feature #891, which allows for leftmost partial matches of UUID values. # Tracked Bugs, sorted by ID. + Fixed bug #208, which addresses various problems with recurring tasks, and diff --git a/src/A3.cpp b/src/A3.cpp index a8b9113f8..1515c7201 100644 --- a/src/A3.cpp +++ b/src/A3.cpp @@ -1145,12 +1145,23 @@ const A3 A3::sequence (const A3& input) const for (unsigned int i = 0; i < uuids.size (); ++i) { - if (ids.size ()) + if (ids.size () + i > 0) sequenced.push_back (Arg ("or", Arg::cat_op)); - sequenced.push_back (Arg ("uuid", Arg::type_string, Arg::cat_dom)); - sequenced.push_back (Arg ("=", Arg::cat_op)); - sequenced.push_back (Arg (uuids[i], Arg::type_string, Arg::cat_literal)); + // A full-length UUID requires a string comparison. + if (uuids[i].length () == 36) + { + sequenced.push_back (Arg ("uuid", Arg::type_string, Arg::cat_dom)); + sequenced.push_back (Arg ("=", Arg::cat_op)); + sequenced.push_back (Arg (uuids[i], Arg::type_string, Arg::cat_literal)); + } + // A UUID fragment is a leftmost comparison. + else + { + sequenced.push_back (Arg ("uuid", Arg::type_string, Arg::cat_dom)); + sequenced.push_back (Arg ("~", Arg::cat_op)); + sequenced.push_back (Arg ("^" + uuids[i], Arg::type_string, Arg::cat_rx)); + } } sequenced.push_back (Arg (")", Arg::cat_op)); @@ -1674,11 +1685,11 @@ bool A3::is_uuid (Nibbler& n, std::string& result) n.save (); result = ""; std::string uuid; - if (n.getUUID (uuid)) + if (n.getPartialUUID (uuid)) { result += uuid; while (n.skip (',') && - n.getUUID (uuid)) + n.getPartialUUID (uuid)) { result += ',' + uuid; } @@ -1997,13 +2008,13 @@ bool A3::extract_uuid ( Nibbler n (input); std::string uuid; - if (n.getUUID (uuid)) + if (n.getPartialUUID (uuid)) { sequence.push_back (uuid); while (n.skip (',')) { - if (!n.getUUID (uuid)) + if (!n.getPartialUUID (uuid)) throw std::string (STRING_A3_UUID_AFTER_COMMA); sequence.push_back (uuid); diff --git a/src/Nibbler.cpp b/src/Nibbler.cpp index ab86430f6..7f7c8dc3c 100644 --- a/src/Nibbler.cpp +++ b/src/Nibbler.cpp @@ -38,7 +38,8 @@ #include #endif -const char* c_digits = "0123456789"; // TODO Not used? +static const char* _uuid_pattern = "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"; +static const unsigned int _uuid_min_length = 8; //////////////////////////////////////////////////////////////////////////////// Nibbler::Nibbler () @@ -613,6 +614,36 @@ bool Nibbler::getUUID (std::string& result) return false; } +//////////////////////////////////////////////////////////////////////////////// +bool Nibbler::getPartialUUID (std::string& result) +{ + std::string::size_type i; + for (i = 0; i < 36 && i < (_length - _cursor); i++) + { + if (_uuid_pattern[i] == 'x' && !isxdigit (_input[_cursor + i])) + break; + + else if (_uuid_pattern[i] == '-' && _input[_cursor + i] != '-') + break; + } + + // If the partial match found is long enough, consider it a match. + if (i >= _uuid_min_length) + { + // Fail if there is another hex digit. + if (_cursor + i < _length && + isxdigit (_input[_cursor + i])) + return false; + + result = _input.substr (_cursor, i); + _cursor += i; + + return true; + } + + return false; +} + //////////////////////////////////////////////////////////////////////////////// // 19980119T070000Z = YYYYMMDDThhmmssZ bool Nibbler::getDateISO (time_t& t) diff --git a/src/Nibbler.h b/src/Nibbler.h index 80da9be59..a816affc6 100644 --- a/src/Nibbler.h +++ b/src/Nibbler.h @@ -75,6 +75,7 @@ public: bool getRx (const std::string&, std::string&); #endif bool getUUID (std::string&); + bool getPartialUUID (std::string&); bool getDateISO (time_t&); #ifdef NIBBLER_FEATURE_DATE bool getDate (const std::string&, time_t&); diff --git a/test/feature.891.t b/test/feature.891.t new file mode 100755 index 000000000..6e2c1dfd2 --- /dev/null +++ b/test/feature.891.t @@ -0,0 +1,192 @@ +#! /usr/bin/perl +################################################################################ +## 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 +## +################################################################################ + +use strict; +use warnings; +use Test::More tests => 36; + +# Create the rc file. +if (open my $fh, '>', 'bug.rc') +{ + print $fh "data.location=.\n"; + close $fh; + ok (-r 'bug.rc', 'Created bug.rc'); +} + +# Feature 891: UUID filter should be uuid.endswith by default +qx{../src/task rc:bug.rc add one}; +qx{../src/task rc:bug.rc add two}; +my $output = qx{../src/task rc:bug.rc 1 info}; +my ($uuid) = $output =~ /UUID\s+(\S{36})/ms; + +$output = qx{../src/task rc:bug.rc $uuid list rc.debug:1}; +like ($output, qr/one/, "Found with $uuid"); + +my ($short) = $uuid =~ /^(.{35})/; +$output = qx{../src/task rc:bug.rc $short list rc.debug:1}; +like ($output, qr/one/, "Found with $short"); + +($short) = $uuid =~ /^(.{34})/; +$output = qx{../src/task rc:bug.rc $short list}; +like ($output, qr/one/, "Found with $short"); + +($short) = $uuid =~ /^(.{33})/; +$output = qx{../src/task rc:bug.rc $short list}; +like ($output, qr/one/, "Found with $short"); + +($short) = $uuid =~ /^(.{32})/; +$output = qx{../src/task rc:bug.rc $short list}; +like ($output, qr/one/, "Found with $short"); + +($short) = $uuid =~ /^(.{31})/; +$output = qx{../src/task rc:bug.rc $short list}; +like ($output, qr/one/, "Found with $short"); + +($short) = $uuid =~ /^(.{30})/; +$output = qx{../src/task rc:bug.rc $short list}; +like ($output, qr/one/, "Found with $short"); + +($short) = $uuid =~ /^(.{29})/; +$output = qx{../src/task rc:bug.rc $short list}; +like ($output, qr/one/, "Found with $short"); + +($short) = $uuid =~ /^(.{28})/; +$output = qx{../src/task rc:bug.rc $short list}; +like ($output, qr/one/, "Found with $short"); + +($short) = $uuid =~ /^(.{27})/; +$output = qx{../src/task rc:bug.rc $short list}; +like ($output, qr/one/, "Found with $short"); + +($short) = $uuid =~ /^(.{26})/; +$output = qx{../src/task rc:bug.rc $short list}; +like ($output, qr/one/, "Found with $short"); + +($short) = $uuid =~ /^(.{25})/; +$output = qx{../src/task rc:bug.rc $short list}; +like ($output, qr/one/, "Found with $short"); + +($short) = $uuid =~ /^(.{24})/; +$output = qx{../src/task rc:bug.rc $short list}; +like ($output, qr/one/, "Found with $short"); + +($short) = $uuid =~ /^(.{23})/; +$output = qx{../src/task rc:bug.rc $short list}; +like ($output, qr/one/, "Found with $short"); + +($short) = $uuid =~ /^(.{22})/; +$output = qx{../src/task rc:bug.rc $short list}; +like ($output, qr/one/, "Found with $short"); + +($short) = $uuid =~ /^(.{21})/; +$output = qx{../src/task rc:bug.rc $short list}; +like ($output, qr/one/, "Found with $short"); + +($short) = $uuid =~ /^(.{20})/; +$output = qx{../src/task rc:bug.rc $short list}; +like ($output, qr/one/, "Found with $short"); + +($short) = $uuid =~ /^(.{19})/; +$output = qx{../src/task rc:bug.rc $short list}; +like ($output, qr/one/, "Found with $short"); + +($short) = $uuid =~ /^(.{18})/; +$output = qx{../src/task rc:bug.rc $short list}; +like ($output, qr/one/, "Found with $short"); + +($short) = $uuid =~ /^(.{17})/; +$output = qx{../src/task rc:bug.rc $short list}; +like ($output, qr/one/, "Found with $short"); + +($short) = $uuid =~ /^(.{16})/; +$output = qx{../src/task rc:bug.rc $short list}; +like ($output, qr/one/, "Found with $short"); + +($short) = $uuid =~ /^(.{15})/; +$output = qx{../src/task rc:bug.rc $short list}; +like ($output, qr/one/, "Found with $short"); + +($short) = $uuid =~ /^(.{14})/; +$output = qx{../src/task rc:bug.rc $short list}; +like ($output, qr/one/, "Found with $short"); + +($short) = $uuid =~ /^(.{13})/; +$output = qx{../src/task rc:bug.rc $short list}; +like ($output, qr/one/, "Found with $short"); + +($short) = $uuid =~ /^(.{12})/; +$output = qx{../src/task rc:bug.rc $short list}; +like ($output, qr/one/, "Found with $short"); + +($short) = $uuid =~ /^(.{11})/; +$output = qx{../src/task rc:bug.rc $short list}; +like ($output, qr/one/, "Found with $short"); + +($short) = $uuid =~ /^(.{10})/; +$output = qx{../src/task rc:bug.rc $short list}; +like ($output, qr/one/, "Found with $short"); + +($short) = $uuid =~ /^(.{9})/; +$output = qx{../src/task rc:bug.rc $short list}; +like ($output, qr/one/, "Found with $short"); + +($short) = $uuid =~ /^(.{8})/; +$output = qx{../src/task rc:bug.rc $short list}; +like ($output, qr/one/, "Found with $short"); + +($short) = $uuid =~ /^(.{7})/; +$output = qx{../src/task rc:bug.rc $short list}; +unlike ($output, qr/one/, "Not found with $short"); + +($short) = $uuid =~ /^(.{6})/; +$output = qx{../src/task rc:bug.rc $short list}; +unlike ($output, qr/one/, "Not found with $short"); + +($short) = $uuid =~ /^(.{5})/; +$output = qx{../src/task rc:bug.rc $short list}; +unlike ($output, qr/one/, "Not found with $short"); + +($short) = $uuid =~ /^(.{4})/; +$output = qx{../src/task rc:bug.rc $short list}; +unlike ($output, qr/one/, "Not found with $short"); + +($short) = $uuid =~ /^(.{3})/; +$output = qx{../src/task rc:bug.rc $short list}; +unlike ($output, qr/one/, "Not found with $short"); + +# Cleanup. +unlink qw(pending.data completed.data undo.data backlog.data synch.key bug.rc); +ok (! -r 'pending.data' && + ! -r 'completed.data' && + ! -r 'undo.data' && + ! -r 'backlog.data' && + ! -r 'synch.key' && + ! -r 'bug.rc', 'Cleanup'); + +exit 0; + diff --git a/test/nibbler.t.cpp b/test/nibbler.t.cpp index 49e7e9809..7404cf931 100644 --- a/test/nibbler.t.cpp +++ b/test/nibbler.t.cpp @@ -39,15 +39,15 @@ int main (int argc, char** argv) { #ifdef NIBBLER_FEATURE_DATE #ifdef NIBBLER_FEATURE_REGEX - UnitTest t (299); + UnitTest t (388); #else - UnitTest t (275); + UnitTest t (364); #endif #else #ifdef NIBBLER_FEATURE_REGEX - UnitTest t (249); + UnitTest t (338); #else - UnitTest t (225); + UnitTest t (314); #endif #endif @@ -347,6 +347,157 @@ int main (int argc, char** argv) t.is (s, "a0b1c2d3-e4f5-A6B7-C8D9-E0F1a2b3c4d5", "uuid 2 -> correct"); t.ok (n.depleted (), "depleted"); + // bool getPartialUUID (std::string&); + t.diag ("Nibbler::getPartialUUID"); + n = Nibbler ("a0b1c2d3-e4f5-A6B7-C8D9-E0F1a2b3c4d5"); + t.ok (n.getPartialUUID (s), "partial uuid [36] found"); + t.is (s, "a0b1c2d3-e4f5-A6B7-C8D9-E0F1a2b3c4d5", "partial uuid [36] -> correct"); + t.ok (n.depleted (), "depleted"); + + n = Nibbler ("a0b1c2d3-e4f5-A6B7-C8D9-E0F1a2b3c4d"); + t.ok (n.getPartialUUID (s), "partial uuid [35] found"); + t.is (s, "a0b1c2d3-e4f5-A6B7-C8D9-E0F1a2b3c4d", "partial uuid [35] -> correct"); + t.ok (n.depleted (), "depleted"); + + n = Nibbler ("a0b1c2d3-e4f5-A6B7-C8D9-E0F1a2b3c4"); + t.ok (n.getPartialUUID (s), "partial uuid [34] found"); + t.is (s, "a0b1c2d3-e4f5-A6B7-C8D9-E0F1a2b3c4", "partial uuid [34] -> correct"); + t.ok (n.depleted (), "depleted"); + + n = Nibbler ("a0b1c2d3-e4f5-A6B7-C8D9-E0F1a2b3c"); + t.ok (n.getPartialUUID (s), "partial uuid [33] found"); + t.is (s, "a0b1c2d3-e4f5-A6B7-C8D9-E0F1a2b3c", "partial uuid [33] -> correct"); + t.ok (n.depleted (), "depleted"); + + n = Nibbler ("a0b1c2d3-e4f5-A6B7-C8D9-E0F1a2b3"); + t.ok (n.getPartialUUID (s), "partial uuid [32] found"); + t.is (s, "a0b1c2d3-e4f5-A6B7-C8D9-E0F1a2b3", "partial uuid [32] -> correct"); + t.ok (n.depleted (), "depleted"); + + n = Nibbler ("a0b1c2d3-e4f5-A6B7-C8D9-E0F1a2b"); + t.ok (n.getPartialUUID (s), "partial uuid [31] found"); + t.is (s, "a0b1c2d3-e4f5-A6B7-C8D9-E0F1a2b", "partial uuid [31] -> correct"); + t.ok (n.depleted (), "depleted"); + + n = Nibbler ("a0b1c2d3-e4f5-A6B7-C8D9-E0F1a2"); + t.ok (n.getPartialUUID (s), "partial uuid [30] found"); + t.is (s, "a0b1c2d3-e4f5-A6B7-C8D9-E0F1a2", "partial uuid [30] -> correct"); + t.ok (n.depleted (), "depleted"); + + n = Nibbler ("a0b1c2d3-e4f5-A6B7-C8D9-E0F1a"); + t.ok (n.getPartialUUID (s), "partial uuid [29] found"); + t.is (s, "a0b1c2d3-e4f5-A6B7-C8D9-E0F1a", "partial uuid [29] -> correct"); + t.ok (n.depleted (), "depleted"); + + n = Nibbler ("a0b1c2d3-e4f5-A6B7-C8D9-E0F1"); + t.ok (n.getPartialUUID (s), "partial uuid [28] found"); + t.is (s, "a0b1c2d3-e4f5-A6B7-C8D9-E0F1", "partial uuid [28] -> correct"); + t.ok (n.depleted (), "depleted"); + + n = Nibbler ("a0b1c2d3-e4f5-A6B7-C8D9-E0F"); + t.ok (n.getPartialUUID (s), "partial uuid [27] found"); + t.is (s, "a0b1c2d3-e4f5-A6B7-C8D9-E0F", "partial uuid [27] -> correct"); + t.ok (n.depleted (), "depleted"); + + n = Nibbler ("a0b1c2d3-e4f5-A6B7-C8D9-E0"); + t.ok (n.getPartialUUID (s), "partial uuid [26] found"); + t.is (s, "a0b1c2d3-e4f5-A6B7-C8D9-E0", "partial uuid [26] -> correct"); + t.ok (n.depleted (), "depleted"); + + n = Nibbler ("a0b1c2d3-e4f5-A6B7-C8D9-E"); + t.ok (n.getPartialUUID (s), "partial uuid [25] found"); + t.is (s, "a0b1c2d3-e4f5-A6B7-C8D9-E", "partial uuid [25] -> correct"); + t.ok (n.depleted (), "depleted"); + + n = Nibbler ("a0b1c2d3-e4f5-A6B7-C8D9-"); + t.ok (n.getPartialUUID (s), "partial uuid [24] found"); + t.is (s, "a0b1c2d3-e4f5-A6B7-C8D9-", "partial uuid [24] -> correct"); + t.ok (n.depleted (), "depleted"); + + n = Nibbler ("a0b1c2d3-e4f5-A6B7-C8D9"); + t.ok (n.getPartialUUID (s), "partial uuid [23] found"); + t.is (s, "a0b1c2d3-e4f5-A6B7-C8D9", "partial uuid [23] -> correct"); + t.ok (n.depleted (), "depleted"); + + n = Nibbler ("a0b1c2d3-e4f5-A6B7-C8D"); + t.ok (n.getPartialUUID (s), "partial uuid [22] found"); + t.is (s, "a0b1c2d3-e4f5-A6B7-C8D", "partial uuid [22] -> correct"); + t.ok (n.depleted (), "depleted"); + + n = Nibbler ("a0b1c2d3-e4f5-A6B7-C8"); + t.ok (n.getPartialUUID (s), "partial uuid [21] found"); + t.is (s, "a0b1c2d3-e4f5-A6B7-C8", "partial uuid [21] -> correct"); + t.ok (n.depleted (), "depleted"); + + n = Nibbler ("a0b1c2d3-e4f5-A6B7-C"); + t.ok (n.getPartialUUID (s), "partial uuid [20] found"); + t.is (s, "a0b1c2d3-e4f5-A6B7-C", "partial uuid [20] -> correct"); + t.ok (n.depleted (), "depleted"); + + n = Nibbler ("a0b1c2d3-e4f5-A6B7-"); + t.ok (n.getPartialUUID (s), "partial uuid [19] found"); + t.is (s, "a0b1c2d3-e4f5-A6B7-", "partial uuid [19] -> correct"); + t.ok (n.depleted (), "depleted"); + + n = Nibbler ("a0b1c2d3-e4f5-A6B7"); + t.ok (n.getPartialUUID (s), "partial uuid [18] found"); + t.is (s, "a0b1c2d3-e4f5-A6B7", "partial uuid [18] -> correct"); + t.ok (n.depleted (), "depleted"); + + n = Nibbler ("a0b1c2d3-e4f5-A6B"); + t.ok (n.getPartialUUID (s), "partial uuid [17] found"); + t.is (s, "a0b1c2d3-e4f5-A6B", "partial uuid [17] -> correct"); + t.ok (n.depleted (), "depleted"); + + n = Nibbler ("a0b1c2d3-e4f5-A6"); + t.ok (n.getPartialUUID (s), "partial uuid [16] found"); + t.is (s, "a0b1c2d3-e4f5-A6", "partial uuid [16] -> correct"); + t.ok (n.depleted (), "depleted"); + + n = Nibbler ("a0b1c2d3-e4f5-A"); + t.ok (n.getPartialUUID (s), "partial uuid [15] found"); + t.is (s, "a0b1c2d3-e4f5-A", "partial uuid [15] -> correct"); + t.ok (n.depleted (), "depleted"); + + n = Nibbler ("a0b1c2d3-e4f5-"); + t.ok (n.getPartialUUID (s), "partial uuid [14] found"); + t.is (s, "a0b1c2d3-e4f5-", "partial uuid [14] -> correct"); + t.ok (n.depleted (), "depleted"); + + n = Nibbler ("a0b1c2d3-e4f5"); + t.ok (n.getPartialUUID (s), "partial uuid [13] found"); + t.is (s, "a0b1c2d3-e4f5", "partial uuid [13] -> correct"); + t.ok (n.depleted (), "depleted"); + + n = Nibbler ("a0b1c2d3-e4f"); + t.ok (n.getPartialUUID (s), "partial uuid [12] found"); + t.is (s, "a0b1c2d3-e4f", "partial uuid [12] -> correct"); + t.ok (n.depleted (), "depleted"); + + n = Nibbler ("a0b1c2d3-e4"); + t.ok (n.getPartialUUID (s), "partial uuid [11] found"); + t.is (s, "a0b1c2d3-e4", "partial uuid [11] -> correct"); + t.ok (n.depleted (), "depleted"); + + n = Nibbler ("a0b1c2d3-e"); + t.ok (n.getPartialUUID (s), "partial uuid [10] found"); + t.is (s, "a0b1c2d3-e", "partial uuid [10] -> correct"); + t.ok (n.depleted (), "depleted"); + + n = Nibbler ("a0b1c2d3-"); + t.ok (n.getPartialUUID (s), "partial uuid [9] found"); + t.is (s, "a0b1c2d3-", "partial uuid [9] -> correct"); + t.ok (n.depleted (), "depleted"); + + n = Nibbler ("a0b1c2d3"); + t.ok (n.getPartialUUID (s), "partial uuid [8] found"); + t.is (s, "a0b1c2d3", "partial uuid [8] -> correct"); + t.ok (n.depleted (), "depleted"); + + n = Nibbler ("a0b1c2d"); + t.notok (n.getPartialUUID (s), "partial uuid [7] not found"); + t.notok (n.depleted (), "not depleted"); + // bool getDateISO (time_t&); t.diag ("Nibbler::getDateISO"); n = Nibbler ("19980119T070000Z");