1<?php
2/* Copyright (c) 1998-2009 ILIAS open source, Extended GPL, see docs/LICENSE */
3
4use PHPUnit\Framework\TestSuite;
5use PHPUnit\Framework\TestCase;
6use PHPUnit\Runner\Filter\Factory as FilterFactory;
7use PHPUnit\Runner\Filter\ExcludeGroupFilterIterator as GroupExcludeFilter;
8
9/**
10* This is the global ILIAS test suite. It searches automatically for
11* components test suites by scanning all Modules/.../test and
12* Services/.../test directories for test suite files.
13*
14* Test suite files are identified automatically, if they are named
15* "ilServices[ServiceName]Suite.php" or ilModules[ModuleName]Suite.php".
16*
17* @author	<alex.killing@gmx.de>
18*/
19class ilGlobalSuite extends TestSuite
20{
21    /**
22     * @var	string
23     */
24    const PHPUNIT_GROUP_FOR_TESTS_REQUIRING_INSTALLED_ILIAS = "needsInstalledILIAS";
25    const REGEX_TEST_FILENAME = "#[a-zA-Z]+Test\.php#";
26    const PHP_UNIT_PARENT_CLASS = TestCase::class;
27
28    /**
29     * Check if there is an installed ILIAS to run tests on.
30     *
31     * TODO: implement me correctly!
32     * @return	bool
33     */
34    public function hasInstalledILIAS()
35    {
36        $ilias_ini_path = __DIR__ . "/../../../ilias.ini.php";
37
38        if (!is_file($ilias_ini_path)) {
39            return false;
40        }
41        require_once './Services/Init/classes/class.ilIniFile.php';
42        $ilias_ini = new ilIniFile($ilias_ini_path);
43        $ilias_ini->read();
44        $client_data_path = $ilias_ini->readVariable("server", "absolute_path") . "/" . $ilias_ini->readVariable("clients", "path");
45
46        if (!is_dir($client_data_path)) {
47            return false;
48        }
49
50        include_once($ilias_ini->readVariable("server", "absolute_path") . "/Services/PHPUnit/config/cfg.phpunit.php");
51
52        if (!isset($_GET["client_id"])) {
53            return false;
54        }
55
56        $phpunit_client = $_GET["client_id"];
57
58        if (!$phpunit_client) {
59            return false;
60        }
61
62        if (!is_file($client_data_path . "/" . $phpunit_client . "/client.ini.php")) {
63            return false;
64        }
65
66        return true;
67    }
68
69    public static function suite()
70    {
71        $suite = new ilGlobalSuite();
72        echo "ILIAS PHPUnit-Tests need installed dev-requirements, please install using 'composer install' in ./libs/composer \n";
73        echo "\n";
74
75        // scan Modules and Services directories
76        $basedirs = array("Services", "Modules");
77
78        foreach ($basedirs as $basedir) {
79            // read current directory
80            $dir = opendir($basedir);
81
82            while ($file = readdir($dir)) {
83                if ($file != "." && $file != ".." && is_dir($basedir . "/" . $file)) {
84                    $suite_path =
85                        $basedir . "/" . $file . "/test/il" . $basedir . $file . "Suite.php";
86                    if (is_file($suite_path)) {
87                        include_once($suite_path);
88
89                        $name = "il" . $basedir . $file . "Suite";
90                        $s = $name::suite();
91                        echo "Adding Suite: " . $name . "\n";
92                        $suite->addTest($s);
93                        //$suite->addTestSuite("ilSettingTest");
94                    }
95                }
96            }
97        }
98
99        $suite = self::addTestFolderToSuite($suite);
100
101        echo "\n";
102
103        if (!$suite->hasInstalledILIAS()) {
104            echo "Removing tests requiring an installed ILIAS.\n";
105            $ff = new FilterFactory();
106            $ff->addFilter(
107                new ReflectionClass(GroupExcludeFilter::class),
108                array(self::PHPUNIT_GROUP_FOR_TESTS_REQUIRING_INSTALLED_ILIAS)
109                );
110            $suite->injectFilter($ff);
111        } else {
112            echo "Found installed ILIAS, running all tests.\n";
113        }
114        return $suite;
115    }
116
117    /**
118     * Find and add all testSuits beneath ILIAS_ROOL/tests - folder
119     *
120     * @param	ilGlobalSuite	$suite
121     * @return	ilGloblaSuite	$suite
122     */
123    protected static function addTestFolderToSuite(ilGlobalSuite $suite)
124    {
125        $test_directories = array("tests");
126        while ($aux_dir = current($test_directories)) {
127            if ($handle = opendir($aux_dir)) {
128                $aux_dir .= DIRECTORY_SEPARATOR;
129                while (false !== ($entry = readdir($handle))) {
130                    if ($entry === '.' || $entry === '..') {
131                        continue;
132                    }
133                    if (is_dir($aux_dir . $entry)) {
134                        $test_directories[] = $aux_dir . $entry;
135                    } else {
136                        if (1 === preg_match(self::REGEX_TEST_FILENAME, $entry)) {
137                            $ref_declared_classes = get_declared_classes();
138                            require_once $aux_dir . "/" . $entry;
139                            $new_declared_classes = array_diff(get_declared_classes(), $ref_declared_classes);
140                            foreach ($new_declared_classes as $entry_class) {
141                                $reflection = new ReflectionClass($entry_class);
142                                if (!$reflection->isAbstract() && $reflection->isSubclassOf(self::PHP_UNIT_PARENT_CLASS)) {
143                                    echo "Adding Test-Suite: " . $entry_class . "\n";
144                                    $suite->addTestSuite($entry_class);
145                                }
146                            }
147                        }
148                    }
149                }
150            }
151            next($test_directories);
152        }
153        return $suite;
154    }
155}
156