Diagnostics

- Added new 'diagnostics' command to assist with bug reporting,
  testing.  It answers questions such as "did you compile it yourself?",
  and more.
- Specifically, it runs a UUID generation test to prove that the UUIDs
  are really unique.
This commit is contained in:
Paul Beckingham
2010-10-20 00:22:20 -04:00
parent 314f64f775
commit 1e37d7a784
16 changed files with 333 additions and 96 deletions

View File

@@ -51,6 +51,7 @@
+ Two new color themes (thanks to Kathryn Andersen). + Two new color themes (thanks to Kathryn Andersen).
+ More localized holiday files for US, CA, SE, DE, FR, UK, ES and NL + More localized holiday files for US, CA, SE, DE, FR, UK, ES and NL
(thanks to T. Charles Yun). (thanks to T. Charles Yun).
+ Added new 'diagnostics' command to help with bug submission, testing.
+ Fixed bug #427, preventing the task edit command to parse annotation + Fixed bug #427, preventing the task edit command to parse annotation
dates with spaces. dates with spaces.
+ Fixed bug #433, making task command output more consistent. + Fixed bug #433, making task command output more consistent.

4
NEWS
View File

@@ -40,6 +40,7 @@ New commands in taskwarrior 1.9.3
file from another taskwarrior user, to sync across machines, for example. file from another taskwarrior user, to sync across machines, for example.
- New 'task push <url>' command to distribute merged changes. - New 'task push <url>' command to distribute merged changes.
- New 'task pull <url>' command to copy data files from a remote location. - New 'task pull <url>' command to copy data files from a remote location.
- New 'diagnostics' command to aid bug reporting.
New configuration options in taskwarrior 1.9.3 New configuration options in taskwarrior 1.9.3
@@ -65,14 +66,13 @@ Newly deprecated features in taskwarrior 1.9.3
obsolete. The 'task show' command warns of the use of these deprecated obsolete. The 'task show' command warns of the use of these deprecated
fields. The synonyms will be removed in a future version of taskwarrior. fields. The synonyms will be removed in a future version of taskwarrior.
--- ---
Taskwarrior has been built and tested on the following configurations: Taskwarrior has been built and tested on the following configurations:
* OS X 10.6 Snow Leopard and 10.5 Leopard * OS X 10.6 Snow Leopard and 10.5 Leopard
* Fedora 13 Goddard, 12 Constantine * Fedora 13 Goddard, 12 Constantine
* Ubuntu 10.04 Lucid Lynx, 9.10 Karmic Koala * Ubuntu 10.10 Maverick Meerkat, 10.04 Lucid Lynx
* Debian Sid * Debian Sid
* Slackware 12.2 * Slackware 12.2
* Arch Linux * Arch Linux

View File

@@ -61,6 +61,8 @@
230 config 230 config
231 show 231 show
235 diagnostics
# 3xx Attributes - must be sequential # 3xx Attributes - must be sequential
300 project 300 project
301 priority 301 priority

View File

@@ -1,7 +1,7 @@
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
// taskwarrior - a command line task list manager. // taskwarrior - a command line task list manager.
// //
// Copyright 2006 - 2010, Paul Beckingham. // Copyright 2006 - 2010, Paul Beckingham, Federico Hernandez.
// All rights reserved. // All rights reserved.
// //
// This program is free software; you can redistribute it and/or modify it under // This program is free software; you can redistribute it and/or modify it under
@@ -75,7 +75,8 @@ bool Cmd::valid (const std::string& input)
// //
// To be a valid custom command: // To be a valid custom command:
// 1. 'input' should autocomplete to one of 'commands'. // 1. 'input' should autocomplete to one of 'commands'.
// 2. the result, canonicalized, should autocomplete to one of 'customreports'. // 2. the result, canonicalized, should autocomplete to one of
// 'customreports'.
bool Cmd::validCustom (const std::string& input) bool Cmd::validCustom (const std::string& input)
{ {
load (); load ();
@@ -152,6 +153,7 @@ void Cmd::load ()
commands.push_back (context.stringtable.get (CMD_CONFIG, "config")); commands.push_back (context.stringtable.get (CMD_CONFIG, "config"));
commands.push_back (context.stringtable.get (CMD_SHOW, "show")); commands.push_back (context.stringtable.get (CMD_SHOW, "show"));
commands.push_back (context.stringtable.get (CMD_DELETE, "delete")); commands.push_back (context.stringtable.get (CMD_DELETE, "delete"));
commands.push_back (context.stringtable.get (CMD_DIAGNOSTICS, "diagnostics"));
commands.push_back (context.stringtable.get (CMD_DONE, "done")); commands.push_back (context.stringtable.get (CMD_DONE, "done"));
commands.push_back (context.stringtable.get (CMD_DUPLICATE, "duplicate")); commands.push_back (context.stringtable.get (CMD_DUPLICATE, "duplicate"));
commands.push_back (context.stringtable.get (CMD_EDIT, "edit")); commands.push_back (context.stringtable.get (CMD_EDIT, "edit"));
@@ -244,6 +246,7 @@ bool Cmd::isReadOnlyCommand ()
command == "ghistory.annual" || command == "ghistory.annual" ||
command == context.stringtable.get (CMD_CALENDAR, "calendar") || command == context.stringtable.get (CMD_CALENDAR, "calendar") ||
command == context.stringtable.get (CMD_COLORS, "colors") || command == context.stringtable.get (CMD_COLORS, "colors") ||
command == context.stringtable.get (CMD_DIAGNOSTICS, "diagnostics") ||
command == context.stringtable.get (CMD_CONFIG, "config") || command == context.stringtable.get (CMD_CONFIG, "config") ||
command == context.stringtable.get (CMD_SHOW, "show") || command == context.stringtable.get (CMD_SHOW, "show") ||
command == context.stringtable.get (CMD_HELP, "help") || command == context.stringtable.get (CMD_HELP, "help") ||

View File

@@ -1,7 +1,7 @@
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
// taskwarrior - a command line task list manager. // taskwarrior - a command line task list manager.
// //
// Copyright 2006 - 2010, Paul Beckingham. // Copyright 2006 - 2010, Paul Beckingham, Federico Hernandez.
// All rights reserved. // All rights reserved.
// //
// This program is free software; you can redistribute it and/or modify it under // This program is free software; you can redistribute it and/or modify it under

View File

@@ -245,6 +245,7 @@ int Context::dispatch (std::string &out)
handleMerge (out); } handleMerge (out); }
else if (cmd.command == "push") { handlePush (out); } else if (cmd.command == "push") { handlePush (out); }
else if (cmd.command == "pull") { handlePull (out); } else if (cmd.command == "pull") { handlePull (out); }
else if (cmd.command == "diagnostics") { handleDiagnostics (out); }
else if (cmd.command == "_projects") { rc = handleCompletionProjects (out); } else if (cmd.command == "_projects") { rc = handleCompletionProjects (out); }
else if (cmd.command == "_tags") { rc = handleCompletionTags (out); } else if (cmd.command == "_tags") { rc = handleCompletionTags (out); }
else if (cmd.command == "_commands") { rc = handleCompletionCommands (out); } else if (cmd.command == "_commands") { rc = handleCompletionCommands (out); }

View File

@@ -13,9 +13,10 @@ task_SOURCES = API.cpp API.h Att.cpp Att.h Cmd.cpp Cmd.h Color.cpp Color.h \
Timer.cpp Timer.h Transport.cpp Transport.h TransportSSH.cpp \ Timer.cpp Timer.h Transport.cpp Transport.h TransportSSH.cpp \
TransportSSH.h TransportRSYNC.cpp TransportRSYNC.h \ TransportSSH.h TransportRSYNC.cpp TransportRSYNC.h \
TransportCurl.cpp TransportCurl.h Tree.cpp Tree.h command.cpp \ TransportCurl.cpp TransportCurl.h Tree.cpp Tree.h command.cpp \
custom.cpp dependency.cpp edit.cpp export.cpp i18n.h import.cpp \ custom.cpp dependency.cpp diag.cpp edit.cpp export.cpp i18n.h \
interactive.cpp main.cpp main.h recur.cpp report.cpp rules.cpp \ import.cpp interactive.cpp main.cpp main.h recur.cpp report.cpp \
rx.cpp rx.h text.cpp text.h util.cpp util.h Uri.cpp Uri.h rules.cpp rx.cpp rx.h text.cpp text.h util.cpp util.h Uri.cpp \
Uri.h
task_CPPFLAGS=$(LUA_CFLAGS) task_CPPFLAGS=$(LUA_CFLAGS)
task_LDFLAGS=$(LUA_LFLAGS) task_LDFLAGS=$(LUA_LFLAGS)

221
src/diag.cpp Normal file
View File

@@ -0,0 +1,221 @@
////////////////////////////////////////////////////////////////////////////////
// taskwarrior - a command line task list manager.
//
// Copyright 2006 - 2010, 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 <iomanip>
#include <sstream>
#include <algorithm>
#include <string>
#include <unistd.h>
#include <stdlib.h>
#include <File.h>
#include <main.h>
#include <util.h>
#include "../auto.h"
#ifdef HAVE_LIBLUA
extern "C"
{
#include <lua.h>
}
#endif
#ifdef HAVE_LIBNCURSES
#include <ncurses.h>
#endif
extern Context context;
////////////////////////////////////////////////////////////////////////////////
// This command will generate output that is intended to help diagnose problems.
//
// Although this will change over time, initially this command will answer the
// kind of questions we always have to ask whenever something is wrong.
void handleDiagnostics (std::string& outs)
{
std::cout << "\n" << PACKAGE_STRING << "\n";
std::cout << " Platform: "
<<
#if defined (DARWIN)
"Darwin"
#elif defined (SOLARIS)
"Solaris"
#elif defined (CYGWIN)
"Cygwin"
#elif defined (OPENBSD)
"OpenBSD"
#elif defined (HAIKU)
"Haiku"
#elif defined (FREEBSD)
"FreeBSD"
#elif defined (LINUX)
"Linux"
#else
"<unknown>"
#endif
<< "\n\n";
// Compiler.
std::cout << "Compiler\n"
#ifdef __VERSION__
<< " Version: " << __VERSION__ << "\n"
#endif
<< " Caps:"
#ifdef __STDC__
<< " +stdc"
#endif
#ifdef __STDC_HOSTED__
<< " +stdc_hosted"
#endif
#ifdef __STDC_VERSION__
<< " +" << __STDC_VERSION__
#endif
#ifdef _POSIX_VERSION
<< " +" << _POSIX_VERSION
#endif
#ifdef _POSIX2_C_VERSION
<< " +" << _POSIX2_C_VERSION
#endif
#ifdef _ILP32
<< " +ILP32"
#endif
#ifdef _LP64
<< " +LP64"
#endif
<< " +c" << sizeof (char)
<< " +i" << sizeof (int)
<< " +l" << sizeof (long)
<< " +vp" << sizeof (void*)
<< "\n\n";
std::cout << "Libraries\n";
// NCurses.
std::cout << " NCurses: "
#ifdef HAVE_LIBNCURSES
<< NCURSES_VERSION
<< " ("
<< NCURSES_VERSION_PATCH
<< ")"
#else
<< "n/a"
#endif
<< "\n";
std::cout << " Readline: "
#ifdef HAVE_LIBREADLINE
<< std::setbase (16) << RL_READLINE_VERSION
#else
<< "n/a"
#endif
<< "\n";
std::cout << " Lua: "
#ifdef HAVE_LIBLUA
<< LUA_RELEASE
#else
<< "n/a"
#endif
<< "\n\n";
std::cout << "Build Features\n"
// Build date.
<< " Built: " << __DATE__ << " " << __TIME__ << "\n"
<< " Caps:"
#ifdef HAVE_LIBPTHREAD
<< " +pthreads"
#else
<< " -pthreads"
#endif
#ifdef HAVE_SRANDOM
<< " +srandom"
#else
<< " -srandom"
#endif
#ifdef HAVE_RANDOM
<< " +random"
#else
<< " -random"
#endif
#ifdef HAVE_UUID
<< " +uuid"
#else
<< " -uuid"
#endif
<< "\n\n";
// Config: .taskrc found, readable, writable
std::cout << "Configuration\n"
<< " File: " << context.config.original_file.data
<< (context.config.original_file.exists () ? " (found)" : " (missing)")
<< ", " << context.config.original_file.size () << " bytes"
<< ", mode "
<< std::setbase (8)
<< context.config.original_file.mode ()
<< "\n";
// Config: data.location found, readable, writable
File location (context.config.get ("data.location"));
std::cout << " Data: " << location.data
<< (location.exists () ? " (found)" : " (missing)")
<< ", " << (location.is_directory () ? "dir" : "?")
<< ", mode "
<< std::setbase (8)
<< location.mode ()
<< "\n\n";
// Generate 1000 UUIDs and verify they are all unique.
std::cout << "Tests\n";
{
std::cout << " UUID gen: ";
std::vector <std::string> uuids;
std::string id;
for (int i = 0; i < 1000; i++)
{
id = uuid ();
if (std::find (uuids.begin (), uuids.end (), id) != uuids.end ())
{
std::cout << "Failed - duplicate UUID at iteration " << i << "\n";
break;
}
else
uuids.push_back (id);
}
if (uuids.size () >= 1000)
std::cout << "1000 unique UUIDs generated.\n";
}
std::cout << "\n";
}
////////////////////////////////////////////////////////////////////////////////

View File

@@ -1,7 +1,7 @@
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
// taskwarrior - a command line task list manager. // taskwarrior - a command line task list manager.
// //
// Copyright 2006 - 2010, Paul Beckingham. // Copyright 2006 - 2010, Paul Beckingham, Federico Hernandez.
// All rights reserved. // All rights reserved.
// //
// This program is free software; you can redistribute it and/or modify it under // This program is free software; you can redistribute it and/or modify it under
@@ -101,6 +101,7 @@
#define CMD_MERGE 232 #define CMD_MERGE 232
#define CMD_PUSH 233 #define CMD_PUSH 233
#define CMD_PULL 234 #define CMD_PULL 234
#define CMD_DIAGNOSTICS 235
// 3xx Attributes // 3xx Attributes
#define ATT_PROJECT 300 #define ATT_PROJECT 300

View File

@@ -92,6 +92,9 @@ int deltaTags (Task&);
int deltaAttributes (Task&); int deltaAttributes (Task&);
int deltaSubstitutions (Task&); int deltaSubstitutions (Task&);
// diag.cpp
void handleDiagnostics (std::string&);
// edit.cpp // edit.cpp
int handleEdit (std::string&); int handleEdit (std::string&);

View File

@@ -236,6 +236,10 @@ int shortUsage (std::string &outs)
table.addCell (row, 1, "task config [name [value | '']]"); table.addCell (row, 1, "task config [name [value | '']]");
table.addCell (row, 2, "Add, modify and remove settings in the task configuration."); table.addCell (row, 2, "Add, modify and remove settings in the task configuration.");
row = table.addRow ();
table.addCell (row, 1, "task diagnostics");
table.addCell (row, 2, "Information needed when reporting a problem.");
row = table.addRow (); row = table.addRow ();
table.addCell (row, 1, "task help"); table.addCell (row, 1, "task help");
table.addCell (row, 2, "Shows the long usage text."); table.addCell (row, 2, "Shows the long usage text.");