Things accomplished at the hackathon
Aaron Crane
- went for a run
- config stuff
Abe Timmerman
Barbie
- Fixed the registrations for the CPAN Testers Wiki (http://wiki.cpantesters.org). Not sure how long this was broken, but thanks to Oriol for alerting me.
- CPAN Testers Reports (http://www.cpantesters.org) is now running on Fastly (http://fastly.com), allowing us to caching some of the pages, and reduce the load on the webserver when trying to recreate reasonably static pages. Also means the routing for anyone viewing the site outside of Europe is going to reduce page load times too. Thanks to Leo Lapworth (LLAP) for showing me the ropes.
- Fixed some bugs in the Reports Mailer, and tidied up the notifications. More bugs to fix, which hopefully will be fixed soon.
- For a long running bug with the Summary panel, which turns out has also been affecting MetaCPAN. After the server crash last year, turns out the base db schema was missing a change to one of the tables (part of the summary chain) and wasn't getting updated. Currently rebuilding, so expect to have the summaries and release data feeds all working again soon.
- Continued to hand over the final keys to Doug Bell (PREACTION), who is now carrying the torch for CPAN Testers. I feel immensely confident that I have left the keys in capable hands, and with the ideas Doug has already shown me, I expect bigger and better things for CPAN Testers' future. Please look after him :)
- Fixed a few bugs in other distributions, a couple related to CPAN Testers.
- Cleaned up some of the CPAN Testers family website templates.
- In the coming weeks, will be collating all the website tests I run prior to updating the CPAN Testers family websites, and handing over to Doug for his new development environment for CPAN Testers. This will hopefully enable easier access to anyone wanting to help fix problems on the websites and backends in the future.
bulk 88
Thursday
- 2 patches were written to deal with perls with XSConfig installed, where there is no easy way to modify the faux-read-only %Config hash unlike with PP Config. Disclaimer, I'm the maintainer of XSConfig. cperl just forks T::H to make it pass with XSConfig, but that isn't abstracted correctly. The first patch which used the CPAN Mock::Config module was decided to be unacceptable after discussion with leont since it added an upstream dep to T::H, and T::H has a no deps other than core policy, since its a core bundled module by p5p. The second patch created a global package var which stored the info needed and could be runtime changed/mocked for testing, instead of needing to runtime change the RO %Config hash.
- A heisenbug in proverun.t took most of Thursday to diagnose. After adding my WIP async code, proverun.t always failed under T::H when doing a "make test" yet never failed when running it alone in console. Stepping, print debugging, or adding sleeps also made it go away. You wouldn't think it, since normally the test harness/tap parser's module stack consists of installed modules, not possibly buggy non-CPAN or CPAN uninstalled modules, but when you do a "make test" on T::H, the uninstalled T::H is the harness that tests the uninstalled T::H. So instead of the "server" being stable version of the framework, and the "client" being the unstable version, both are the unstable version. This makes you wonder where is the bug. The bug was eventually discovered to be a override sub ref being assigned to a glob in a child class, and the glob/sub in that child class never existed, instead the meth was inherited from a base class but the dev made a mistake in thinking it was implemented in the child class when it wasn't. The dev even ironically commented in the source code on the side effects of the heisenbug and didn't know why it was happened from when he wrote the code, but in practice the bug wasn't seen in real life, so the comment was wrong, until I replaced the IO layer and the symptons that dev described in the comment happen in practice. Because the STDOUT of proverun.t can be interrogated with perl's -t operator, and T::H did class selection based on the result of -t operator, the override sub was never called under the async IO layer, but was called when run under console. The override method was supposed to suppress T::H in a .t from writing to STDOUT. STDOUT should not be getting written to by T::H in the .t, since the .t was Test::More testing Test::Harness inside the same proc, and Test::Harness was corrupting the TAP stream by writing to STDOUT and causing corruption that Test::Harness in a outer proc (the make test proc) was reading in and thus failing. make_tool->seperate_proc->test::harness for real->seperate_proc->.t->test::more->test::harness was the app stack for proverun.t.
- In some places inside T::H, perl exceptions from other parts of T::H are trapped and stored in objects, but some/most/many .t'es in T::H's test suite, never fetch the error/exception data from objects, ever. So serious errors (dies that I added during development) that should break the T::H .ts were being swallowed without a trace by the .t. This couldn't be found without extensive single stepping of T::H's code and made adding die()s seemingly never execute. I didn't suspect exception swallowing, until I as an experiment did a unpack('P1', "\x01\x00\x00\x00") to force the perl proc to SEGV instead of die() since I started to not trust the die()s I wrote. When I discovered the SEGV executed, but the die() in the next statement right below didn't seem to execute, I knew exceptions were being blindly swallowed and to start single stepping.
- Since speed is the only thing I care about, in discussion of replacing Test::Builder, since I never use anything fancier than Test::More, I benchmarked Test2::Bundle::More vs legacy Test::More. Found Test2::Bundle::More 45% faster than Test::More in execution time of sub ok(). Reported findings to Exodist. Told him my positive feelings and did not participate in any other Test2 discussion that day, or on retrospect, ever again during QAH since I dont have much skin in T::B vs T2 debate.
- Met Mithaldu offline for first time ever. A fellow Win32 Perl user I've known for a long time online.
Friday
- Tap::Parser::Iterator::Process was split into a Unix (really generic/any OS) and Windows class. Design complexity was that multiple CPAN modules do Tap::Parser::Iterator::Process->new() and the implementation of a T::H process had to goto the correct implementation. For stability reasons and because the actual async IO on Win32 subs are a separate XS module on CPAN, the Unix process class continues to work on Win32 in serial testing mode, just like it was before my code. T::H has its own object class called TAP::Object and it was never designed for runtime dynamic class selection where a creating a base class instance actually creates a obj of a derived type, not the type requested. Infinite recursion and perl stack exhaustion happened on the first try as *Tap::Parser::Iterator::Process->new(Tap::Parser::Iterator::Process->new(Tap::Parser::Iterator::Process->new()))* happened. Since T::H has its own object system, that uses "_initialize" methods instead of perl standard "new" methods, the 2nd try called an empty stub/default "_initialize" in TAP::Object instead of the intended Tap::Parser::Iterator::Process::* namespace "_initialize". The prototype of _initialize does not allow changing the classname unlike perl standard new methods. Use of a stepping debugger proved essential to writing this code/patch. Also T::H extensively uses closures and anon subs and sub factories to implement C++ private object members in Perl, which is unperl-like and this had to be reversed and minimized in some places.
- A Win32 IO Completion Port implementation of Tap::Parser::Iterator::Process was added. Difficulties included that "reads" must be reattempted, if no newline was found in the data that was returned by an async read, and since Windows IO Completion are a FIFO queue in which a read packet for ANY .t proc can be returned in a unpredictable order, yet a Tap::Parser::Iterator::Process->next() (really a read/fetch/get method) must return a line on a specific fixed .t proc, a system had to be invented to emulate sync blocking IO from 1 proc ontop of a queue where IO was poped from ANY proc. The emulation was done by a while loop that runs until 1 read or 1 line of TAP is available from the specific .t proc, and reads and lines of TAP from other .t procs are parsed and queued in the Iterator objects for those other .t procs. Eventually a ->next() will be called on those other Iterator objects which will non-blocking drain the parsed TAP lines. Although this design can cause the parsed TAP line buffers to grow very large and grow unequally nothing can really be done about when round robin queue must be emulated ontop of a queue where the largest TAP emitter .t proc gets the largest amount of timeslices. Remember that .t files all emit a different TAP tests per second than other .t files due to inherant underlying work, and OS thread scheduler, and number of CPU cores differences. Round robin is a bad idea for .t files, since .t files that are sleeping should get 0 time slices from T::H, but Multiplexer.pm without a working IO::Select requires that round robin (iterating a perl array from index 0 going up) work.
- The first implementation of introducing a new IO layer, specific for Win32 (or any OS) into T::H had the random proc queue, but since only 1 child proc .t was ever started by T::H for the marjority of T::H's test suite, no sorting of read events into respectic procs needed to be done, since there was only 1 running child proc at a time. A PP assert made sure the opaque perl ref sent through the async queue and poped off the queue when the read event is delivered was identical to $self. The assert compared the PID stored in the opaque obj and self obj (both are of type Tap::Parser::Iterator::Process). The assert 1 out of 10 runs failed in multiplexer t since by chance the order of the events coming off the queue when there were 3 procs running happened to be in the order the 3 procs were originally launches by multiplexer.t. Increasing the amount of child procs from 3 to 6 made the events be almost always 10 out of 10 times, interleves between different procs rather than by chance all the events coming from 1 proc. This helped to diagnose the race condition and the the assert was removed when the previous bullet point on this page was implemented by me.
Saturday
- Fixed a memory leak in Tap::Parser::Iterator::Process::Windows. The leak was caused by me not including a statement that was in Tap::Parser::Iterator::Process::Unix which broke a circular reference, where $self of Tap::Parser::Iterator::Process::* was closed over in next() method, since the next() method prototype had no arguments, not even $self. @_ was designed to be empty on entry to the method since T::H's last major dev work in ~2007. Changing the prototype of next method to make it sane should be done but was not tried due to high risk of breaking other parts of T::H's code and tests, and possibly compat CPAN addon modules to T::H. The memory leak was discovered by writing a temporary DESTROY method and breakpointing it. Bizarrely and unperl-like, there isn't a single DESTROY method in T::H. T::H instead uses circular references and C++ style explicit memory management with *_finish* methods to break circular references.
- Added an Win32 async compatible IO loop to TAP::Parser::Multiplexer. Complexity includes that T::H is a pull architecture as leont describes in https://github.com/Perl-Toolchain-Gang/Test-Harness/issues/30 . I hacked on a push option to Tap::Parser::Iterator::Process::Windows, which is implemented by a combination of, "if set to push mode, forbid pulls (blocking IO AKA hangs)" and pushing data off the Win OS pipe handle into Iterator objects causes later possibly blocking "read" methods, to be guaranteed non-blocking, as the data is already queued in PP space, which matches the existing Multiplexer architecture. The push option I added adds a POC that a more efficient POSIX event loop than IO::Select (aio/epoll/kqueue) could be added in the future to T::H. Other difficulties include analyzing what seem to be or are circular references and convincing oneself that they are not bugs but by design. I discussed a number of designs with leont that we both rejected for various reasons. One rejected redesign of Multiplexer were weak references (not used at all by T::H previously and not used currently after my improvements) and callbacks from the Iterator object back to the Multiplexer object in a outer stack frame. Since non-parallel T::H harness test runs use _aggregate_single and not _aggregate_parallel, there may or may not be a Multiplexer object in the callstack at any random call into an Iterator object. Using caller() or CPAN modules that use basically perl debugging facilities to walk the callstack, to look for a Multiplexer object to notify which Iterator object/Parser object was ready to read was also rejected.
- went to cpan river meeting
Christian Walde
- released https://metacpan.org/release/MITHALDU/PPI-1.221_01 which greatly increases test coverage to allow parsing changes without fear of hidden regressions
Doug Bell
- Started Rex deploy for CPANTesters -- http://github.com/cpan-testers/cpantesters-deploy/
- Started tracking project meta-goals -- http://github.com/cpan-testers/cpantesters-project/issues
Wendy van Dijk
- Went shopping every day, sometimes twice a day, for fruit, vegetables, cookies, nuts, soda, tea and other things
- Spent several hours every day preparing the fruit and vegetables, and cleaning after the other people
- Attended three meetings (Test2 & Test::Builder, River of CPAN, Test2), took notes, took a bit part in some discussions, and transcribed the notes and sending the texts to Chad, Neil and Ricardo.
- Succeeded in wasting many people's time with silliness and booze.
version 11 saved on 24/04/16 10:04 by Barbie
Home | Tags | Recent changes | History