#!/usr/bin/env php
<?php

// Activate the autoloader
require_once(dirname(dirname(__FILE__)).'/src/resources/global_resources.php');

// Throw a bunch of junk in the autoload path
DaGdConfig::$config['general.autoload_search'][] = dirname(__FILE__);
DaGdConfig::$config['general.autoload_search'][] = dirname(__FILE__).'/unit';

final class TestCLI extends DaGdCLIProgram {
  public function run() {
    parent::run();

    $runner = new DaGdTestRunner();
    $runner->setBaseUrl($this->param('--url')->getValue());

    $cb = new DaGdTestResultCLICallback($this);
    $runner->setResultsCallback($cb);

    $runner->arm(
      id(new DaGdContentTypeTest('/', 'text/plain'))
        ->addGroup('shorten')
        ->setAccept('text/plain'));

    $runner->arm(
      id(new DaGdContentTypeTest('/', 'text/html'))
        ->addGroup('shorten')
        ->setAccept('text/html'));

    $runner->arm(
      id(new DaGdRegexTest('/', '@various conditions@'))
        ->addGroup('shorten'));

    $runner->arm(
      id(new DaGdRegexTest('/?text=0', '@<form@'))
        ->addGroup('shorten'));

    $runner->arm(
      id(new DaGdRegexTest('/', '@<form@'))
        ->addGroup('shorten')
        ->setAccept('text/html'));

    $runner->arm(
      id(new DaGdRegexTest('/', '@<html lang="en">@'))
        ->addGroup('shorten')
        ->setAccept('text/html'));

    $runner->arm(
      id(
        new DaGdHeaderRegexTest(
          '/',
          'Content-Length',
          '@^0$@',
          true))
        ->addGroup('shorten')
        ->setAccept('text/html'));

    /*********** routing by method ***********/
    // TODO: Needs "same-route, different-request-method, different-controller"
    // tests added (which will require test-specification applications and
    // changes to the route-map.

    $runner->arm(
      id(new DaGdResponseCodeTest('/ip', 405))
        ->setMethod('POST')
        ->addGroup('routing'));

    $runner->arm(
      id(new DaGdResponseCodeTest('/ec/Test', 405))
        ->setMethod('PUT')
        ->addGroup('routing'));

    $runner->arm(
      id(new DaGdResponseCodeTest('/ua', 200))
        ->setMethod('HEAD')
        ->addGroup('routing'));


    /*********** /ip ***********/

    $runner->arm(
      id(new DaGdRegexTest('/ip', '@(?:[0-9]+\.){3}[0-9]+$@'))
        ->addGroup('ip'));
    $runner->arm(
      id(new DaGdRegexTest('/ip', '@(?:[0-9]+\.){3}[0-9]@'))
        ->addGroup('ip')
        ->setAccept('text/html'));

    /*********** /ua ***********/

    $runner->arm(
      id(new DaGdRegexTest('/ua', '@^monkey$@'))
        ->addGroup('ua')
        ->setUserAgent('monkey'));
    $runner->arm(
      id(new DaGdRegexTest('/ua', '@>monkey@'))
        ->addGroup('ua')
        ->setUserAgent('monkey')
        ->setAccept('text/html'));

    /*********** /ec/CodeBlock ***********/

    $runner->arm(
      id(new DaGdRegexTest('/ec/CodeBlock', '@^[0-9]+$@'))
        ->addGroup('ec'));
    $runner->arm(
      id(new DaGdRegexTest('/ec/CodeBlock?lang=en', '@^[0-9]+$@'))
        ->addGroup('ec'));
    $runner->arm(
      id(new DaGdRegexTest('/ec/CodeBlock?lang=fr', '@^[0-9]+$@'))
        ->addGroup('ec'));

    /************ /w/xxxxxxx ************/

    /* // Ensure that whois is functioning. */
    $runner->arm(
      id(new DaGdRegexTest('/w/google.com', '@ns1.google.com@i'))
        ->addGroup('whois'));
    //$runner->arm(
    //  id(new DaGdRegexTest('/w/da.gd', '@bill.ns.cloudflare.com@i')));
    $runner->arm(
      id(new DaGdRegexTest('/w/4.2.2.2', '@Level 3 Parent@'))
        ->addGroup('whois'));
    $runner->arm(
      id(new DaGdRegexTest('/w/74.94.18.108', '@OrgAbusePhone@'))
        ->addGroup('whois'));
    //$runner->arm(
    //  id(
    //    new DaGdRegexTest(
    //      '/w/2001:470:8:624:211c:aaaa:1111:1111',
    //      '@Hurricane Electric@'))
    //    ->addGroup('whois'));
    $runner->arm(
      id(new DaGdRegexTest('/w/trees.network','@NC@'))
        ->addGroup('whois'));
    $runner->arm(
      id(new DaGdRegexTest('/w/denic.de','@Changed:@'))
        ->addGroup('whois'));
    $runner->arm(
      id(new DaGdRegexTest('/w/eurid.eu','@Registrar:@'))
        ->addGroup('whois'));
    //$runner->arm(
    //  id(
    //    new DaGdRegexTest(
    //      '/w/donuts.co',
    //      '@Registrant Organization: Donuts Inc.@'))
    //    ->addGroup('whois'));
    //$runner->arm(
    //  id(
    //    new DaGdRegexTest(
    //      '/w/usi.edu',
    //      '@University of Southern Indiana@'))
    //    ->addGroup('whois'));
    $runner->arm(
      id(
        new DaGdRegexTest(
          '/w/dcma.mil',
          '@DoD Network Information Center@'))
        ->addGroup('whois'));
    $runner->arm(
      id(
        new DaGdRegexTest(
          '/w/AS31976',
          '@Red Hat@'))
        ->addGroup('whois'));
    $runner->arm(
      id(
        new DaGdRegexTest(
          '/w/as4653',
          '@Data 3 Limited@'))
        ->addGroup('whois'));

    /************ /headers/xxxxxxx ************/

    $runner->arm(
      id(new DaGdRegexTest('/headers', '@Host: @'))
        ->addGroup('headers'));
    $runner->arm(
      id(new DaGdRegexTest('/headers', '@X-DaGd-Proxy: @', true))
        ->addGroup('headers'));
    $runner->arm(
      id(new DaGdRegexTest('/headers', '@Authorization: foobar@'))
        ->setRequestHeader('Authorization', 'foobar')
        ->addGroup('headers'));
    $runner->arm(
      id(new DaGdRegexTest('/headers/google.com', '@Server: gws@'))
        ->addGroup('headers'));
    $runner->arm(
      id(new DaGdRegexTest('/headers/http://google.com/', '@Server: gws@'))
        ->addGroup('headers'));

    /************ /up/xxxxxxx ************/
    $runner->arm(
      id(new DaGdResponseCodeTest('/up/google.com', 200))
        ->setAccept('text/html')
        ->addGroup('up'));
    $runner->arm(
      id(new DaGdRegexTest('/up/google.com', '@^200$@'))
        ->addGroup('up'));
    $runner->arm(
      id(new DaGdRegexTest('/up/https://encrypted.google.com/', '@^200$@'))
        ->addGroup('up'));
    $runner->arm(
      id(new DaGdRegexTest('/up/http://google.com/404', '@^404$@'))
        ->addGroup('up'));
    $runner->arm(
      id(new DaGdRegexTest('/up/?url=google.com', '@^200$@'))
        ->addGroup('up'));
    $runner->arm(
      id(new DaGdRegexTest('/up?url=https://encrypted.google.com/', '@^200$@'))
        ->addGroup('up'));
    $runner->arm(
      id(new DaGdRegexTest('/up/?url=http://google.com/404', '@^404$@'))
        ->addGroup('up'));

    /************ hardcoded redirects ************/
    $runner->arm(
      id(new DaGdResponseCodeTest('/et/750009720', 302))
        ->addGroup('et'));
    $runner->arm(
      id(new DaGdResponseCodeTest('/rhbz/1883609', 302))
        ->addGroup('rhbz'));
    $runner->arm(
      id(new DaGdHeaderRegexTest(
        '/rhbz/1883609',
        'Location',
        '@^https://bugzilla\.redhat\.com/show_bug\.cgi\?id=1883609$@'))
      ->addGroup('rhbz'));
    $runner->arm(
      id(new DaGdHeaderRegexTest(
        '/rhbz/1883609/',
	'Location',
	'@^https://bugzilla\.redhat\.com/show_bug\.cgi\?id=1883609$@'))
      ->addGroup('rhbz'));

    /************ /host/xxxxxxx ************/
    $runner->arm(
      id(new DaGdRegexTest('/host/ipv6.google.com', '@:@'))
        ->addGroup('host'));
    $runner->arm(
      id(new DaGdRegexTest('/host/google.com', '@[0-9]\.@'))
        ->addGroup('host'));
    $runner->arm(
      id(new DaGdRegexTest('/host/google.com?noipv6', '@:@', true))
        ->addGroup('host'));
    $runner->arm(
      id(new DaGdRegexTest('/host/4.2.2.1', '@a.resolvers.level3.net@'))
        ->addGroup('host'));

    /************ /break/ ************/
    $runner->arm(
      id(new DaGdResponseCodeTest('/break', 500))
        ->addGroup('break')
        ->addGroup('noprod'));
    $runner->arm(
      id(new DaGdRegexTest('/break', '@500 - internal server error@'))
        ->addGroup('break')
        ->addGroup('noprod'));

    /************ /image/xxxxxxx/[xxxxxxx] ************/
    $runner->arm(
      id(new DaGdContentTypeTest('/image/200x200', 'image/png'))
        ->addGroup('image')
        ->setAccept('text/html'));
    $runner->arm(
      id(new DaGdContentTypeTest('/image/200x200', 'image/png'))
        ->addGroup('image')
        ->setAccept('text/plain'));
    $runner->arm(
      id(new DaGdContentTypeTest('/image/10x10.jpg', 'image/jpeg'))
        ->setAccept('text/plain'));
    $runner->arm(
      id(new DaGdContentTypeTest('/image/30x20.gif?bgcolor=333333', 'image/gif'))
        ->addGroup('image')
        ->setAccept('text/html'));
    $runner->arm(
      id(new DaGdResponseCodeTest('/image/300', 400))
        ->addGroup('image'));
    $runner->arm(
      id(new DaGdResponseCodeTest('/image/300000000x1212121221', 400))
        ->addGroup('image'));

    /************ /status/xxxxxxx/[xxxxxxx] ************/
    $runner->arm(
      id(new DaGdResponseCodeTest('/status/400', 400))
        ->addGroup('status'));
    $runner->arm(
      id(new DaGdResponseCodeTest('/status/403', 403))
        ->addGroup('status'));
    $runner->arm(
      id(new DaGdResponseCodeTest('/status/321/hi', 321))
        ->addGroup('status'));
    $runner->arm(
      id(new DaGdResponseRegexTest('/status/321/hi', '@321 hi$@'))
        ->addGroup('status'));
    $runner->arm(
      id(new DaGdResponseRegexTest('/status/321/hi%20there', '@321 hi there$@'))
        ->addGroup('status'));
    $runner->arm(
      id(new DaGdResponseRegexTest('/status/321/?message=hi%20there', '@321 hi there$@'))
        ->addGroup('status'));

    /************ /isp/[xxxxxxx] ************/
    $runner->arm(
      id(
        new DaGdRegexTest(
          '/isp/127.0.0.1',
          '@^Internet Assigned Numbers Authority@'))
        ->addGroup('isp'));
    $runner->arm(
      id(new DaGdRegexTest('/isp/69.171.237.16', '@Facebook, Inc\.@'))
        ->addGroup('isp'));
    $runner->arm(
      id(new DaGdRegexTest('/isp/1.1.1.1', '@Cloudflare@'))
        ->addGroup('isp'));
    $runner->arm(
      id(
        new DaGdRegexTest(
          '/isp/2607:f8b0:4000:812::200e',
          '@Google@'))
        ->addGroup('isp'));

    /************ /help ************/
    $runner->arm(
      id(new DaGdRegexTest('/help', '@pixels: <a href="/image/200x400/png"@'))
      ->addGroup('help')
      ->addGroup('deprecated')
      ->setAccept('text/html'));
    $runner->arm(
      id(
        new DaGdRegexTest(
          '/help?url_prefix=dagd%20&url_separator=%20&url_request_sep=%20--',
          '@image 200x400 png@'))
        ->setAccept('text/plain')
        ->addGroup('help')
        ->addGroup('deprecated'));

    /************ /dns/[xxxxxxx] ************/
    $runner->arm(
      id(new DaGdRegexTest('/dns/google.com', '@IN NS@'))
        ->addGroup('dns'));

    $runner->arm(
      id(new DaGdRegexTest('/dns/google.com', '@IN A@'))
        ->addGroup('dns'));

    /************ /s/[xxxxxxx] ************/
    $runner->arm(
      id(
        new DaGdRegexTest(
          '/s?url=http://google.com&shorturl=g',
          '@/g@'))
        ->setPreparatory(true)
        ->addGroup('shorten'));

    $runner->arm(
      id(
        new DaGdRegexTest(
          '/s?url=http://facebook.com/&shorturl=fbook',
          '@/fbook@'))
        ->setPreparatory(true)
        ->addGroup('shorten'));

    $runner->arm(
      id(
        new DaGdRegexTest(
          '/s?url=https://getfedora.org&shorturl=sstest',
          '@/sstest@'))
        ->setPreparatory(true)
        ->addGroup('shorten'));

    $runner->arm(
      id(
        new DaGdRegexTest(
          '/s?url=http://example.com/&shorturl=example',
          '@/example@'))
        ->setAccept('text/plain')
        ->setPreparatory(true)
        ->addGroup('shorten'));

    $runner->arm(
      id(
        new DaGdRegexTest(
          '/s?url=http://2.example.com/&shorturl=2example',
          '@/2example@'))
        ->setAccept('text/html')
        ->setPreparatory(true)
        ->addGroup('shorten'));

    $runner->arm(
      id(new DaGdRegexTest('/coshorten/g', '@http://google.com@'))
        ->addGroup('shorten')
        ->addGroup('coshorten'));

    $runner->arm(
      id(new DaGdRegexTest('/coshorten/g/foo', '@http://google.com/foo@'))
        ->addGroup('shorten')
        ->addGroup('coshorten'));

    $runner->arm(
      id(
        new DaGdRegexTest(
          '/coshorten/g/foo/bar',
          '@http://google.com/foo/bar@'))
        ->addGroup('shorten')
        ->addGroup('coshorten'));

    $runner->arm(
      id(
        new DaGdRegexTest(
          '/coshorten/g/foo/bar?animal=monkey',
          '@http://google.com/foo/bar\?animal=monkey@'))
        ->addGroup('shorten')
        ->addGroup('coshorten'));

    $runner->arm(
      id(
        new DaGdRegexTest(
          '/g+',
          '@http://google.com@'))
        ->addGroup('shorten')
        ->addGroup('coshorten'));

    $runner->arm(
      id(
        new DaGdRegexTest(
          '/g+/foo',
          '@http://google.com/foo@'))
        ->addGroup('shorten')
        ->addGroup('coshorten'));

    $runner->arm(
      id(
        new DaGdRegexTest(
          '/g+/foo/bar?animal=monkey',
          '@http://google.com/foo/bar\?animal=monkey@'))
        ->addGroup('shorten')
        ->addGroup('coshorten'));

    $runner->arm(
      id(new DaGdResponseCodeTest('/g', 302))
        ->addGroup('shorten'));
    $runner->arm(
      id(new DaGdResponseCodeTest('/g/foo', 302))
        ->addGroup('shorten'));
    $runner->arm(
      id(new DaGdResponseCodeTest('/fbook', 302))
        ->addGroup('shorten'));
    // If Authorization is set, we should abort the request.
    $runner->arm(
      id(new DaGdResponseCodeTest('/fbook', 403))
        ->setRequestHeader('Authorization', 'foo')
        ->addGroup('shorten'));
    $runner->arm(
      id(new DaGdResponseCodeTest('/fbook?url=foo', 302))
        ->addGroup('shorten'));

    $runner->arm(
      id(new DaGdHeaderRegexTest('/fbook?url=foo', 'Location', '@\?url=foo$@'))
        ->addGroup('shorten'));
    $runner->arm(
      id(new DaGdHeaderRegexTest('/g', 'Location', '@^http://google.com$@'))
        ->addGroup('shorten'));
    $runner->arm(
      id(
        new DaGdHeaderRegexTest(
          '/g/?foo=bar',
          'Location',
          '@^http://google.com\?foo=bar$@')));
    $runner->arm(
      id(
        new DaGdHeaderRegexTest(
          '/g/foo',
          'Location',
          '@^http://google.com/foo$@'))
        ->addGroup('shorten'));

    $runner->arm(
      id(
        new DaGdRegexTest(
          '/s?url=https://some.spam.url&shorturl=spam',
          '@Blacklisted long URL@'))
        ->addGroup('shorten')
        ->addGroup('noprod'));

    $runner->arm(
      id(new DaGdResponseCodeTest('/s?url=https://some.spam.url', 400))
        ->addGroup('shorten')
        ->addGroup('noprod'));

    $runner->arm(
      id(new DaGdResponseCodeTest('/s?url=https://foo(){bar;}', 400))
        ->addGroup('shorten')
        ->addGroup('noprod'));

    /************ /stats/ ************/
    $runner->arm(
      id(new DaGdResponseCodeTest('/stats/g', 200))
      ->addGroup('stats'));

    $runner->arm(
      id(new DaGdResponseCodeTest('/stats/doesnotexist', 404))
      ->setAccept('text/html')
      ->addGroup('stats'));

    /************ /screenshot/xxxxxxx ************/
    $runner->arm(
      id(new DaGdResponseCodeTest('/screenshot/doesnotexist', 404))
      ->addGroup('screenshot'));

    //$runner->arm(
    //  id(new DaGdContentTypeTest('/screenshot/sstest', 'image/jpeg'))
    //    ->addGroup('screenshot')
    //    ->setAccept('image/jpeg'));

    //$runner->arm(
    //  id(
    //    new DaGdHeaderRegexTest(
    //      '/screenshot/sstest',
    //      'Content-Length',
    //      '@^0$@',
    //      true))
    //    ->addGroup('screenshot'));

    //$runner->arm(
    //  id(
    //    new DaGdRegexTest(
    //      '/stats/g',
    //      '@accesses: \d@'))
    //    ->addGroup('stats'));

    /************ ?strip ************/
    $runner->arm(
      id(new DaGdRegexTest('/ip', '@\n$@'))
        ->addGroup('ip')
        ->addGroup('strip'));
    $runner->arm(
      id(new DaGdRegexTest('/ip?strip=0', '@\n$@'))
        ->addGroup('ip')
        ->addGroup('strip'));
    $runner->arm(
      id(new DaGdRegexTest('/ip?strip', '@[0-9]$@'))
        ->addGroup('ip')
        ->addGroup('strip'));
    $runner->arm(
      id(new DaGdRegexTest('/ip?strip=1', '@[0-9]$@'))
        ->addGroup('ip')
        ->addGroup('strip'));

    /************ /roll/ ************/
    $runner->arm(
      id(new DaGdResponseCodeTest('/roll/3d', 404))
        ->addGroup('roll'));
    $runner->arm(
      id(new DaGdResponseCodeTest('/roll/3d2', 200))
        ->setAccept('text/html')
        ->addGroup('roll'));
    $runner->arm(
      id(new DaGdRegexTest('/roll/d9', '@^[0-9]$@'))
        ->addGroup('roll'));
    $runner->arm(
      id(new DaGdRegexTest('/roll/3d1', '@^3$@'))
        ->addGroup('roll'));
    $runner->arm(
      id(new DaGdRegexTest('/roll/3d1+3', '@^6$@'))
        ->addGroup('roll'));
    $runner->arm(
      id(new DaGdRegexTest('/roll/3d1-1', '@^2$@'))
        ->addGroup('roll'));
    $runner->arm(
      id(new DaGdRegexTest('/roll/3d10', '@^\d+$@'))
        ->addGroup('roll'));

    /************ /leftpad/ ************/
    $runner->arm(
      id(new DaGdRegexTest('/leftpad/10/z/foo', '@^z{7}foo$@'))
        ->addGroup('leftpad'));

    /************ session cookies ************/
    $runner->arm(
      id(new DaGdHeaderRegexTest('/?darkmode', 'Set-Cookie', '@^DaGdSession_@'))
        ->addGroup('darkmode')
        ->addGroup('session')
        ->setAccept('text/html'));
    $runner->arm(
      id(new DaGdSessionRegexTest('/?darkmode', 'darkmode', '@^true$@'))
        ->addGroup('darkmode')
        ->addGroup('session')
        ->setAccept('text/html'));
    $runner->arm(
      id(new DaGdSessionRegexTest('/?darkmode=1', 'darkmode', '@^true$@'))
        ->addGroup('darkmode')
        ->addGroup('session')
        ->setAccept('text/html'));
    $runner->arm(
      id(new DaGdSessionRegexTest('/?darkmode=0', 'darkmode', '@^false$@'))
        ->addGroup('darkmode')
        ->addGroup('session')
        ->setAccept('text/html'));

    /************ /cow/ ************/
    $expected = <<<'EOD'
 ________________________
< I am moo, hear me roar >
 ------------------------
  \
   \   \_\_    _/_/
    \      \__/
           (AA)\_______
           (__)\       )\/\
            <> ||----w |
               ||     ||

EOD;
    $runner
      ->arm(
        id(
          new DaGdExactMatchTest(
            '/cow?text=I%20am%20moo,%20hear%20me%20roar&cow=moose&eyes=AA&tongue=<>',
            $expected))
        ->addGroup('cow'));

    $runner
      ->arm(
        id(
          new DaGdExactMatchTest(
            '/cow?say=I%20am%20moo,%20hear%20me%20roar&cow=moose&eyes=AA&tongue=<>',
            $expected))
        ->addGroup('cow'));

    $runner->arm(
      id(new DaGdContentTypeTest('/cow?text=1&say=hi', 'text/plain'))
        ->addGroup('cow')
        ->setAccept('text/html'));

    $runner->arm(
      id(new DaGdContentTypeTest('/cow?text=0&say=hi', 'text/html'))
        ->addGroup('cow')
        ->setAccept('text/html'));

    $runner->arm(
      id(new DaGdContentTypeTest('/cow?text=0&say=hi', 'text/html'))
        ->addGroup('cow')
        ->setAccept('text/plain'));

    $runner->arm(
      id(new DaGdContentTypeTest('/cow?text=foo', 'text/plain'))
        ->addGroup('cow')
        ->setAccept('text/plain'));

    $runner->arm(
      id(new DaGdContentTypeTest('/cow?text=foo', 'text/plain'))
        ->addGroup('cow')
        ->setAccept('text/html'));

    $runner->arm(
      id(new DaGdContentTypeTest('/cow?say=foo', 'text/html'))
        ->addGroup('cow')
        ->setAccept('text/html'));

    /************ Tag unit tests ************/
    $runner->arm(
      id(
        new DaGdTagUnitTest(
          tag('h1', 'hello'),
          '<h1>hello</h1>'))
      ->addGroup('unit')
      ->addGroup('tag'));

    $runner->arm(
      id(
        new DaGdTagUnitTest(
          tag('br'),
          '<br/>'))
      ->addGroup('unit')
      ->addGroup('tag'));

    $runner->arm(
      id(
        new DaGdTagUnitTest(
          tag('a', 'quote "quote" quote', array('href' => '/"foo"')),
          '<a href="/&quot;foo&quot;">quote "quote" quote</a>'))
      ->addGroup('unit')
      ->addGroup('tag'));

    $runner->arm(
      id(
        new DaGdTagUnitTest(
          tag('p', 'Foo & Bar, LLC.'),
          '<p>Foo &amp; Bar, LLC.</p>'))
      ->addGroup('unit')
      ->addGroup('tag'));

    $runner->arm(
      id(
        new DaGdTagUnitTest(
          tag(
            'p',
            array(
              'multiple',
              'strings',
              tag(
                'b',
                'and this is bold'
              )
            )
          ),
          '<p>multiplestrings<b>and this is bold</b></p>'))
      ->addGroup('unit')
      ->addGroup('tag'));

    $runner->arm(
      id(
        new DaGdTagUnitTest(
          tag(
            'p',
            array(
              'multiple',
              'strings',
              tag('b', 'and this is bold'),
              array(
                tag('p', 'an array in an array?'),
                array(
                  tag('i', 'in an array'),
                  array(
                    tag('u', 'yo dawg'),
                  ),
                ),
              ),
            )
          ),
          '<p>multiplestrings<b>and this is bold</b><p>an array in an '.
          'array?</p><i>in an array</i><u>yo dawg</u></p>'))
      ->addGroup('unit')
      ->addGroup('tag'));

    $runner->arm(
      id(
        new DaGdTagUnitTest(
          tag(
            'p',
            array(
              'multiple',
              'strings',
              tag(
                'b',
                array(
                  'and this is bold',
                  tag(
                    'i',
                    'and this is bold and italic'
                  ),
                )
              ),
            )
          ),
          '<p>multiplestrings<b>and this is bold<i>and this is '.
          'bold and italic</i></b></p>'))
      ->addGroup('unit')
      ->addGroup('tag'));

    $runner->arm(
      id(new DaGdUnitTestAssertThrows())
      ->addGroup('unit'));

    $runner->arm(
      id(new DaGdUnitTestAssertDaGdSessionBasics())
      ->addGroup('unit'));

    $groups = $this->param('--groups');
    if ($groups->getGiven()) {
      $runner->setGroupsFilter(explode(',', $groups->getValue()));
    }

    $exclude = $this->param('--exclude-groups');
    if ($exclude->getGiven()) {
      $runner->setGroupsExcludeFilter(explode(',', $exclude->getValue()));
    }

    // If we're given the flag to skip preparatory tests, then don't run them.
    $runner->setRunPreparatory(!$this->param('--skip-preparatory')->getGiven());

    // Set concurrency/forks
    $runner->setConcurrency($this->param('--forks')->getValue());

    $runner->run();

    echo chr(27)."[1;32m Passed        : ".$runner->getPasses().chr(27)."[0m"."\n";
    echo chr(27)."[1;31m Failed        : ".$runner->getFailures().chr(27)."[0m"."\n";
    echo chr(27)."[1;33m Tolerated Fail: ".$runner->getToleratedFailures().chr(27).
      "[0m"."\n";

    exit($runner->getReturnCode());
  }
}

$testcli = new TestCLI();
$testcli->setName('dagd-test');
$testcli->setDescription('da.gd test suite runner');
$testcli->addParameter(
  id(new DaGdCLIArgument)
    ->setName('--groups')
    ->setShortname('-g')
    ->setDescription(
      'A comma-separated list of test groups to limit to. Defaults to '.
      'everything.'));
$testcli->addParameter(
  id(new DaGdCLIArgument)
    ->setName('--exclude-groups')
    ->setShortname('-x')
    ->setDescription(
      'A comma-separated list of test groups to exclude. Overrides --groups.'));
$testcli->addParameter(
  id(new DaGdCLIArgument)
    ->setName('--url')
    ->setShortname('-u')
    ->setDefault('http://localhost:8080')
    ->setDescription(
      'The dagd instance to test on. Defaults to http://localhost:8080 for '.
      'use the test container.'));
$testcli->addParameter(
  id(new DaGdCLIArgument)
    ->setName('--forks')
    ->setShortname('-f')
    ->setDefault(5)
    ->setDescription(
      'How many forks to use to run tests. Defaults to 5 (somewhat '.
      'arbitrarily).'));
$testcli->addParameter(
  id(new DaGdCLIFlag)
    ->setName('--skip-preparatory')
    ->setShortname('-P')
    ->setDescription(
      'Skip preparatory tests which otherwise get run at the beginning '.
      'regardless of which group filters are set. If you know the group '.
      'you are testing does not depend on them, this is how you can disable '.
      'them.'));
$testcli->addParameter(
  id(new DaGdCLIFlag)
    ->setName('--debug-args')
    ->setShortname('-D')
    ->setDescription('Debug argument parsing'));
$testcli->addParameter(
  id(new DaGdCLIFlag)
    ->setName('--help')
    ->setShortname('-h')
    ->setDescription('Show program help'));
$testcli->execute($argv);
