summaryrefslogtreecommitdiff
path: root/indra/llcommon/tests
AgeCommit message (Collapse)Author
2012-02-15Preliminary pipe support for LLProcess.Nat Goodspeed
Add LLProcess::FileParam to specify how to construct each child's standard file slot, with lots of comments about features designed but not yet implemented. The point is to design it with enough flexibility to be able to extend to foreseeable use cases. Add LLProcess::Params::files to collect up to 3 FileParam items. Naturally this extends the accepted LLSD syntax as well. Implement type="" (child inherits parent file descriptor) and "pipe" (parent constructs anonymous pipe to pass to child). Add LLProcess::FILESLOT enum, plus methods: getReadPipe(FILESLOT), getOptReadPipe(FILESLOT) getWritePipe(), getOptWritePipe() getPipeName(FILESLOT): placeholder implementation for now Add LLProcess::ReadPipe and WritePipe classes, as returned by get*Pipe(). WritePipe supports get_ostream() method for streaming to child stdin. ReadPipe supports get_istream() method for reading from child stdout/stderr. It also provides getPump() returning LLEventPump& so interested parties can listen for arrival of new data on the aforementioned std::istream. For "pipe" slots, instantiate appropriate *Pipe class. ReadPipe and WritePipe classes are pure virtual bases for ReadPipeImpl and WritePipeImpl, respectively: all implementation data are hidden in the latter classes, visible only in llprocess.cpp. In fact each *PipeImpl class registers itself for "mainloop" ticks, attempting nonblocking I/O to the underlying apr_file_t on each tick. Data are buffered in a boost::asio::streambuf, which bridges between std::[io]stream and the APR I/O calls. Sanity-test ReadPipeImpl by using a pipe to absorb the Python "SyntaxError" output from the successful syntax_error test, rather than alarming the user. Add first few unit tests for validating FileParam. More tests coming!
2012-02-13Use per-frame ticks on "mainloop" LLEventPump to update LLProcess.Nat Goodspeed
When we reimplemented LLProcess on APR, necessitating APR's funny callback mechanism to sense child-process status, every isRunning() or getStatus() call called the APR poll function that calls ALL registered LLProcess callbacks. In other words, every time any consumer called any LLProcess::isRunning() method, all LLProcess callbacks were redundantly fired. Change that so that the single APR poll function is called once per frame, courtesy of the "mainloop" LLEventPump. Once per viewer frame should be well within the realtime duration in which it's reasonable to expect child-process status to change. In effect, this changes LLProcess's public API to introduce a dependency on "mainloop" ticks. Add such ticks to llprocess_test.cpp as well.
2012-02-13Add unit tests for LLProcess::Status functionality.Nat Goodspeed
2012-02-07Use os.path.normcase(os.path.normpath()) when comparing directories.Nat Goodspeed
Once again we've been bitten by comparison failure between "c:\somepath" and "C:\somepath". Normalize paths in both Python helper scripts to make that comparison more robust.
2012-02-07Convert LLProcess implementation from platform-specific to using APR.Nat Goodspeed
Include logic to engage Linden apr_procattr_autokill_set() extension: on Windows, magic CreateProcess() flag must be pushed down into apr_proc_create() level. When using an APR package without that extension, present implementation should lock (e.g.) SLVoice.exe lifespan to viewer's on Windows XP but probably won't on Windows 7: need magic flag on CreateProcess(). Using APR child-termination callback requires us to define state (e.g. LLProcess::RUNNING). Take the opportunity to present Status, capturing state and (if terminated) rc or signal number; but since most of the time all caller really wants is to log the outcome, also present status string, encapsulating logic to examine state and describe exited-with-rc vs. killed-by-signal. New Status logic may report clearer results in the case of a Windows child process killed by exception. Clarify that static LLProcess::isRunning(handle) overload is only for use when the original LLProcess object has been destroyed: really only for unit tests. We necessarily retain our original platform-specific implementations for just that one method. (Nonstatic isRunning() no longer calls static method.) Clarify log output from llprocess_test.cpp in a couple places.
2012-01-30Expose 'handle' as well as 'id' on LLProcess objects.Nat Goodspeed
On Posix, these and the corresponding getProcessID()/getProcessHandle() accessors produce the same pid_t value; but on Windows, it's useful to distinguish an int-like 'id' useful to human log readers versus an opaque 'handle' for passing to platform-specific API functions. So make the distinction in a platform-independent way.
2012-01-21Convert LLProcess consumers from LLSD to LLProcess::Params block.Nat Goodspeed
Using a Params block gives compile-time checking against attribute typos. One might inadvertently set myLLSD["autofill"] = false and only discover it when things behave strangely at runtime; but trying to set myParams.autofill will produce a compile error. However, it's excellent that the same LLProcess::create() method can accept either LLProcess::Params or a properly-constructed LLSD block.
2012-01-20Per Richard, replace LLProcessLauncher with LLProcess.Nat Goodspeed
LLProcessLauncher had the somewhat fuzzy mandate of (1) accumulating parameters with which to launch a child process and (2) sometimes tracking the lifespan of the ensuing child process. But a valid LLProcessLauncher object might or might not have ever been associated with an actual child process. LLProcess specifically tracks a child process. In effect, it's a fairly thin wrapper around a process HANDLE (on Windows) or pid_t (elsewhere), with lifespan management thrown in. A static LLProcess::create() method launches a new child; create() accepts an LLSD bundle with child parameters. So building up a parameter bundle is deferred to LLSD rather than conflated with the process management object. Reconcile all known LLProcessLauncher consumers in the viewer code base, notably the class unit tests.
2012-01-18Make embedded Python scripts compatible with Python 2.5 *SIGH*Nat Goodspeed
Apparently our TeamCity build machines are still not up to Python 2.6.
2012-01-18Add tests for implicit-kill-on-destroy, also orphan() method.Nat Goodspeed
2012-01-17Add tests for child-process args management and for kill() method.Nat Goodspeed
2012-01-17Refactor llprocesslauncher_test.cpp for better code reuse.Nat Goodspeed
Instead of free python() and python_out() functions containing a local temporary LLProcessLauncher instance, with a 'tweak' callback param to "do stuff" to that inaccessible object, change to a PythonProcessLauncher class that sets up a (public) LLProcessLauncher member, then allows you to run() or run() and then readfile() the output. Now you can construct an instance and tweak to your heart's content -- without funky callback syntax -- before running the script. Move all such helpers from TUT fixture struct to namespace scope. While fixture-struct methods can freely call one another, introducing a nested class gets awkward: constructor must explicitly require and bind a fixture-struct pointer or reference. Namespace scope solves this. (Truthfully, I only put them in the fixture struct originally because I thought it necessary for calling ensure() et al. But ensure() and friends are free functions; need only qualify them with tut:: namespace.)
2012-01-17Add first couple of LLProcessLauncher tests.Nat Goodspeed
Run INTEGRATION_TEST_llprocesslauncher using setpython.py so we can find the Python interpreter of interest. Introduce python() function to run a Python script specified using NamedTempFile conventions. Introduce a convention by which we can read output from a Python script using only the limited pre-January-2012 LLProcessLauncher API. Introduce python_out() function to leverage that convention. Exercise a couple of LLProcessLauncher methods using all the above.
2012-01-13Extract APR and temp-fixture-file helper code to indra/test.Nat Goodspeed
Specifically: Introduce ManageAPR class in indra/test/manageapr.h. This is useful for a simple test program without lots of static constructors. Extract NamedTempFile from llsdserialize_test.cpp to indra/test/ namedtempfile.h. Refactor to use APR file operations rather than platform- dependent APIs. Use NamedTempFile for llprocesslauncher_test.cpp.
2012-01-12Add LLStreamQueue::size() and tests to exercise it.Nat Goodspeed
2012-01-05Introduce LLStreamQueue to buffer nonblocking I/O.Nat Goodspeed
Add unit tests to verify basic functionality.
2011-12-23Fix sleep(0.5) to sleep(1) -- truncation to int makes that dubious.Nat Goodspeed
2011-12-23Should we expect EOF on one pipe before we finish reading the other?Nat Goodspeed
Defend test against the ambiguous answer to that question by not recording, or testing for, EOF history events. Enrich output for history-verification failures: display whole history array.
2011-12-23Automated merge with ssh://hg.lindenlab.com/nat/viewer-leapNat Goodspeed
2011-12-23Make pipe-management logic more robust.Nat Goodspeed
Previous logic was vulnerable to the case in which both pipes reached EOF in the same loop iteration. Now we use std::list instead of std::vector, allowing us to iterate and delete with a single pass.
2011-12-22Comment out lookup table used only by commented-out code.Nat Goodspeed
Otherwise the unreferenced declaration causes a fatal warning.
2011-12-22Never call apr_proc_wait() inside child_status_callback().Nat Goodspeed
Quiet the temporary child_status_callback() output. Add a bit of diagnostic info if apr_proc_wait() returns anything but APR_CHILD_DONE.
2011-12-22Add child_status_callback() function and arrange to call periodically.Nat Goodspeed
At least on OS X 10.7, a call to apr_proc_wait(APR_NOWAIT) in fact seems to block the caller. So instead of polling apr_proc_wait(), use APR callback mechanism (apr_proc_other_child_register() et al.) and poll that using apr_proc_other_child_refresh_all(). Evidently this polls the underlying system waitpid(), but the internal call seems to better support nonblocking. On arrival in the child_status_callback(APR_OC_REASON_DEATH) call, though, apr_proc_wait() produces ECHILD: the child process in question has already been reaped. The OS-encoded wait() status does get passed to the callback, but then we have to use OS-dependent macros to tease apart voluntary termination vs. killed by signal... a bit of a hole in APR's abstraction layer. Wrap ensure_equals() calls with a macro to explain which comparison failed.
2011-12-21Tweak llprocesslauncher_test.cpp to run properly on Windows.Nat Goodspeed
Fix EOL issues: "\r\n" vs. "\n". On Windows, requesting a read in nonblocking mode can produce EAGAIN instead of EWOULDBLOCK.
2011-12-21Change llprocesslauncher_test.cpp eyeballing to program verification.Nat Goodspeed
That is, where before we just flung stuff to stdout with the expectation that a human user would verify, replace with assertions in the test code itself. Quiet previous noise on stdout. Introduce a temp script file that produces output on both stdout and stderr, with sleep() calls so we predictably have to wait for it. Track and then verify the history of our interaction with the child process, noting especially EWOULDBLOCK attempts.
2011-12-21Fix llprocesslauncher_test.cpp to work on Windows.Nat Goodspeed
2011-12-21Add unit-test module for LLProcessLauncher.Nat Goodspeed
As always with llcommon, this is expressed as an "integration test" to sidestep a circular dependency: the llcommon build depends on its unit tests, but all our unit tests depend on llcommon. Initial test code is more for human verification than automated verification: does APR's child-process management in fact support nonblocking operations?
2011-09-09merge changes for storm-1590Oz Linden
2011-09-08Corrected license information in llsingleton_test.cpp.Logan Dethrow
2011-09-07Automated merge with http://hg.secondlife.com/viewer-developmentNat Goodspeed
2011-09-07STORM-1541: Add LLInstanceTracker tests for active-iterator asserts.Nat Goodspeed
The recent class-static LLInstanceTracker::instance_iter and key_iter reference count is intended to guard against deleting an instance of an LLInstanceTracker subclass during iteration. Add tests for that functionality.
2011-09-07Merge. Fixed issue with LLProxy code related to changes to the LLSocket ↵Logan Dethrow
interface.
2011-09-01MergeLogan Dethrow
2011-09-01Clarified the reason for adding the deleteSingleton method to LLSingleton. ↵Logan Dethrow
Added a simple unit test to verify the functionality of the deleteSingleton method.
2011-08-31Automated merge with http://hg.secondlife.com/viewer-developmentRichard Nelson
2011-08-24Re-add 3 llinstancetracker tests disabled by changeset 1ead63777bf6.Nat Goodspeed
Fix LLInstanceTracker::key_iter constructor param; accepting InstanceMap::iterator by non-const reference relied on Microsoft extension that accepts non-const reference to an rvalue. Given typical iterator implementation, simply accept by value instead, which makes gcc happy too.
2011-08-19better unit test for nested brackets in string replacementRichard Linden
2011-08-19fix for not properly handling nested brackets inRichard Linden
string replacement, e.g. [[FOO]]
2011-07-27fix for gccRichard Nelson
2011-07-26fixed buildRichard Nelson
2011-07-26mergeRichard Nelson
2011-07-26removed last vestiges of llinstancetracerscopedguardRichard Nelson
2011-07-19More FormatMessage compile errors, try again to fixNat Goodspeed
2011-07-19Fix copy/paste error in swiped FormatMessage() example code.Nat Goodspeed
2011-07-19Per Josh's comments in http://codereview.lindenlab.com/6510035/Nat Goodspeed
Instead of low-level open(O_CREAT | O_EXCL) loop on all platforms, use GetTempFileName() on Windows and mkstemp() elsewhere. Don't append a final newline to NamedTempFile: use caller's data literally. Tweak a couple comments.
2011-07-16Use raw-string syntax for other Windows pathnames inserted to Python.Nat Goodspeed
2011-07-16Use raw-string syntax for Python string containing Windows pathname.Nat Goodspeed
Consider this pathname for llsdserialize_test.cpp: C:\nats\indra\llcommon\tests\llsdserialize_test.cpp Embed that in a Python string literal: 'C:\nats\indra\llcommon\tests\llsdserialize_test.cpp' and you get a string containing: C: ats\indra\llcommon ests\llsdserialize_test.cpp where the \n became a newline and the \t became a tab character. Hopefully Python raw-string syntax r'C:\etc\etc' works better.
2011-07-15Use C++ __FILE__ rather than Python __file__ to find indra work area.Nat Goodspeed
In this case, the Python code in question is being written from a C++ string literal to a temp script file in a platform-dependent temp directory -- so the Python __file__ value tells you nothing about the location of the repository checkout. Embedding __FILE__ from the containing C++ source file works better.
2011-07-15If we're going to need indra.base.llsd, have to munge sys.path.Nat Goodspeed
And at that point, the Python logic needed to bring in the llsd module is big enough to warrant capturing it in a separate string variable common to multiple tests.
2011-07-15Not all TC agents have llbase.llsd, fall back to indra.base.llsdNat Goodspeed