Exception types pretty much mirror what TorCtl has (protocol error, socket
error, and controller closed) with a base type users can catch instead. One
difference though is that if stem functions raise a socket.error (without
documenting that they do) then that's a bug - those errors should cuase a
stem.types.SocketError instead.
The system functions are mostly best-effort, platform specific attempts to
retrieve data and usually don't have meaningful information to provide back
to the caller via exceptions. I'm defaulting to have them return None, with
an optional arg for having them raise IOError exceptions on failure instead.
I've gone back and forth on the fencepost here a few times, and I'm still not
positive if this is the right choice. Might change this later if it doesn't
work out.
Changing the conventional usage of util imports from "from stem.util import X"
to simple imports (not pulling them into our namespace). There's some
exceptions to fully qualified util usage where it hurts readability (often the
case with stem.util.term), but explite paths will be the more common case.
Finally abandoning my custom logging implementation for the python builtin
logging module. It's far more customizable, standardized, and what users would
expect from a library like this. The only disadvantage is that it doesn't
buffer past events so we lose anything prior to adding a handler.
Rewrite of arm's utility for parsing proc contents, changes including better
error handling and refacotring for stem's coding conventions and commenting.
While writing the PROTOCOLINFO response handler I needed a system util for
querying tor's pwd, which works best with proc information, so pulling it all
in. For now most of this isn't being exercised, but will be later.
General unit tests to exercise the ControlLine class with PROTOCOLINFO output.
This also has a minor fix so we throw an IndexError rather than ValueError when
pop_mapping() is called while empty.
Tired of having 'test' autocompletion trip up on the sample rc file, so moving
it into the test directory. It's probably not of much interest to general
library users anyway.
Making a string subclass to help with the parsing of controller output. Most
entries are space separated lists of elements, which this class has functions
to easily parse. For controller messages that don't follow this pattern we can
still treat it as a normal string.
Next is to add header documentation and tests.
Integration tests can have custom behavior via a testrc, which is simple for
now, and will grow as tests become more complex. Previously I was loading a
static settings.cfg but that was stupid. The user's config file should neither
be hardcoded nor under version control. This change also includes the config
loading in the status output to stdout.
Several imporvements for the integration tests, most notably including...
- Test configurability via a 'test/settings.cfg' file
- Thread safety for runner usage
- Vastly better startup time for how integration tests run by default...
- Reusing data directory so we don't need to request as much from authorities
when starting (faster startup and less burden on them). Users can opt for a
fresh temporary directory instead by setting 'test.integ.test_directory' to
a blank value.
- Starting tests when bootstraping reaches 5%. This is enough for tests that
don't require network activity to run, and we can explicitly run those
tests by setting the 'test.integ.run.online' option. This change also means
that we can now run integration tests while offline.
A previous commit to suppress errors from the close() method in python 2.7 also
suppressed the following asserts. These asserts still work with 2.7 so removing
them from the try block.
In writing the stem integ tests I needed a function for starting tor then
blocking for its bootstraping to complete. Yesterday Jake mentioned that he
could use a launch_tor() function in TorCtl so I'm generalizing this code and
moving it into the stem lib.
The message integration tests had compatability issues with...
- Newer python versions (2.6 -> 2.7) due to an unexpected failure when calling
close() on the socket's file object. We're operating with a closed socket at
that time so all bets are off about if this should/shouldn't raise so the
difference in behavior just warranted a testing workaround.
- Older tor versions don't support 'GETINFO config-text'. I've left this as a
TODO note for now and will add a version check for that test later.
Adding integration tests for basic control port communication, exercising...
- connection failure
- bad commands
- bad getinfo queries
- general getinfo queries
- setevent/basic event parsing
This also includes fixes for a variety of issues found while testing.
Moving the integ runner module from 'test/integ/runner.py' to 'test/runner.py'.
The 'test/unit/*' and 'test/integ/*' are for test cases, and will later be
kinda crowded. The runner is special since it doesn't test, but rather provides
the runtime context for the integ tests so probably best to keep this separate
from the rest.
Stealing arm's getTorPid and getBsdJailId from the torTools util, generalizing
both functions to be for arbitrary processes rather than just tor. This also
adds unit tests for get_pid and a simple exercise of get_bsd_jail_id (I can't
really test the later since I'm not on BSD).
Making a Runner class which will be available to integration tests. This both
better modularizes the code and will allow for us to give runtime context to
the tests.
First draft for the startup/shutdown of integration tests. This...
- makes a test directory
- generates a torrc
- starts a tor instance, waiting until its bootstrap completes (timing out if
it gets stuck)
- runs tests (not done yet - those are next)
- shuts down the tor instance
This'll certainly go through some refactoring to better modularize, but it's
functional as-is.
Integration tests and other things will be stored via configuration files
(hardcoding data in source is a horrible thing and you have no excuse unless
you're writing in LISP). This is being stolen from the arm codebase, with the
code refactored for this project's conventions, some fixes to better generalize
the util, and vastly improved documentation.
Tom has been using the config util a bit for his torperf rewrite and having
difficulties so hopefully this will make its usage easier.
Adding a unit test and fix for when the input file is derived from a socket
that's never been connected. I'm suspicious that this won't catch disconnects
that accur a little while into the socket's use, but I'll need to implement
integration tests for that. Guess that's next...
Expanding the ControlMessage unit tests to cover causes of protocol errors, and
fixing an issue that this revealed where it was possable for a malformed line
prefix to go undetected (if, say, a dropped character caused a valid line
divider to fall into that place).
This is a functional rewrite of the sendAndRecv TorCtl functionality. It
follows a similar pattern, having a couple threads to continually pull the
socket and provide event notifications. This still needs testing, better
exception handling, and some more thought about the ControlMessage api.
Adding some simple utility functions that I'll need later. These are rewrites
of their arm counterparts, which I wrote before discovering the subprocess
module.
Making the test runner accept arguments for the type of tests to be ran. The
integration tests especially will take a while when they're implemented so
letting the user specify the use cases for those.
This included copying and refactoring some basic utilities from arm for
enumerations and terminal text attributes.
According to PEP8 [1] both functions and variable names should use the
underscore naming convention (ie, 'my_var') rather than camel case ('myVar').
This is a little weird for me and python standard libraries use both, but I see
a readability advantage to this for functions and my previous approach of using
camel case just for variables is kinda weird. Hence switching to the 'right'
convention while the codebase is still tiny.
As an added bonus this conforms with torctl...
[1] http://www.python.org/dev/peps/pep-0008/
Starting with a simple (but non-trivial) class that will be needed for handling
PROTOCOLINFO responses. This is partly to establish conventions for
documentation and unit tests.