diff --git a/.tests/fixtures/fixture_admin.xml b/.tests/fixtures/fixture_admin.xml new file mode 100644 index 0000000..a8319bb --- /dev/null +++ b/.tests/fixtures/fixture_admin.xml @@ -0,0 +1,17 @@ + + + + + + + + + + + 1 + admin + $2y$10$7OvZrKgonVZM9lkzrTbiou.CVhO3HjPk5y0W9L68fVwPs/osBRIMq + + + + diff --git a/.tests/fixtures/fixture_empty.xml b/.tests/fixtures/fixture_empty.xml new file mode 100644 index 0000000..51c44ba --- /dev/null +++ b/.tests/fixtures/fixture_empty.xml @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/.tests/lib/BaseDatabaseTestCase.php b/.tests/lib/BaseDatabaseTestCase.php new file mode 100644 index 0000000..6740020 --- /dev/null +++ b/.tests/lib/BaseDatabaseTestCase.php @@ -0,0 +1,171 @@ +load(); + $dotenv->required(['DB_HOST', 'DB_NAME', 'DB_USER', 'DB_PASS']); + } + + $db_host = getenv('DB_HOST'); + $db_name = getenv('DB_NAME'); + $db_user = getenv('DB_USER'); + $db_pass = getenv('DB_PASS'); + $db_port = getenv('DB_PORT') ?: NULL; + $db_dsn = "mysql:dbname={$db_name};host={$db_host}"; + if (!empty($db_port)) { + $db_dsn .= ";port={$db_port}"; + } + + // pdo connection + if (self::$pdo == null) { + self::$pdo = new PDO($db_dsn, $db_user, $db_pass);; + } + } + + public static function tearDownAfterClass() { + self::$pdo = null; + } + + /** + * Set up database connection + * This will also override uDb class connection + * + * @return PHPUnit_Extensions_Database_DB_IDatabaseConnection + */ + public function getConnection() { + if ($this->conn === null) { + $this->conn = $this->createDefaultDBConnection(self::$pdo, getenv('DB_NAME')); + } + return $this->conn; + } + + /** + * Create data set from xml fixture + * + * @return PHPUnit_Extensions_Database_DataSet_IDataSet + */ + protected function getDataSet() { + return $this->createMySQLXMLDataSet(__DIR__ . '/../fixtures/fixture_empty.xml'); + } + + /** + * Insert to database from array + * + * @param string $table Table name + * @param array $rowsArr Array of rows + * @return int|null Last insert id if available, NULL otherwise + */ + private function pdoInsert($table, $rowsArr = []) { + $ret = NULL; + if (!empty($rowsArr)) { + $values = ':' . implode(', :', array_keys($rowsArr)); + $columns = implode(', ', array_keys($rowsArr)); + $query = "INSERT INTO $table ($columns) VALUES ($values)"; + $stmt = self::$pdo->prepare($query); + if ($stmt !== false) { + $stmt->execute(array_combine(explode(', ', $values), array_values($rowsArr))); + } + $ret = self::$pdo->lastInsertId(); + } + return $ret; + } + + /** + * Get single column from first row of query result + * + * @param string $query SQL query + * @param int $columnNumber Optional column number (default is first column) + * @return string|bool Column or false if no data + */ + protected function pdoGetColumn($query, $columnNumber = 0) { + $column = false; + $stmt = self::$pdo->query($query); + if ($stmt !== false) { + $column = $stmt->fetchColumn($columnNumber); + $stmt->closeCursor(); + } + return $column; + } + + /** + * Insert user data to database + * If parameters are omitted they default test values are used + * + * @param string $user User login + * @param string $pass User password + * @return int|bool User id or false on error + */ + protected function addTestUser($user = NULL, $pass = NULL) { + if (is_null($user)) { $user = $this->testUser; } + if (is_null($pass)) { $pass = $this->testPass; } + return $this->pdoInsert('users', [ 'login' => $user, 'password' => $pass ]); + } + + /** + * Insert track data to database. + * If parameters are omitted they default test values are used + * + * @param int $userId Optional track id + * @param string $trackName Optional track name + * @param string $comment Optional comment + * @return int|bool Track id or false on error + */ + protected function addTestTrack($userId = NULL, $trackName = NULL, $comment = NULL) { + if (is_null($userId)) { $userId = $this->testUserId; } + if (is_null($trackName)) { $trackName = $this->testTrackName; } + if (is_null($comment)) { $comment = $this->testComment; } + return $this->pdoInsert('tracks', [ 'user_id' => $userId, 'name' => $trackName, 'comment' => $comment ]); + } + + /** + * Insert position data to database + * If parameters are omitted they default test values are used + * + * @param int $userId + * @param int $trackId + * @param int $timeStamp + * @param double $latitude + * @param double $longitude + * @return int|bool Position id or false on error + */ + protected function addTestPosition($userId = NULL, $trackId = NULL, $timeStamp = NULL, $latitude = NULL, $longitude = NULL) { + if (is_null($userId)) { $userId = $this->testUserId; } + if (is_null($trackId)) { $trackId = $this->testTrackId; } + if (is_null($timeStamp)) { $timeStamp = $this->testTimestamp; } + if (is_null($latitude)) { $latitude = $this->testLat; } + if (is_null($longitude)) { $longitude = $this->testLon; } + + return $this->pdoInsert('positions', [ "user_id" => $userId, "track_id" => $trackId, "time" => date("Y-m-d H:m:s", $timeStamp), "latitude" => $latitude, "longitude" => $longitude ]); + } +} +?> diff --git a/.tests/lib/UloggerAPITestCase.php b/.tests/lib/UloggerAPITestCase.php new file mode 100644 index 0000000..bdc0336 --- /dev/null +++ b/.tests/lib/UloggerAPITestCase.php @@ -0,0 +1,52 @@ +load(); + $dotenv->required(['ULOGGER_URL']); + } + + $url = getenv('ULOGGER_URL'); + + $this->http = new GuzzleHttp\Client([ 'base_uri' => $url, 'cookies' => true ]); + } + + public function tearDown() { + parent::tearDown(); + $this->http = null; + } + + protected function getDataSet() { + return $this->createMySQLXMLDataSet(__DIR__ . '/../fixtures/fixture_admin.xml'); + } + + /** + * Authenticate on server + * @param string $user Login + * + * @return bool true on success, false otherwise + */ + public function authenticate($user = NULL, $pass = NULL) { + + if (is_null($user)) { $user = $this->testAdminUser; } + if (is_null($pass)) { $pass = $this->testAdminPass; } + + $options = [ + 'http_errors' => false, + 'form_params' => [ 'action' => 'auth', 'user' => $user, 'pass' => $pass ], + ]; + + $response = $this->http->post('/client/index.php', $options); + return ($response->getStatusCode() == 200); + } +} +?> diff --git a/.tests/lib/UloggerDatabaseTestCase.php b/.tests/lib/UloggerDatabaseTestCase.php new file mode 100644 index 0000000..ae114db --- /dev/null +++ b/.tests/lib/UloggerDatabaseTestCase.php @@ -0,0 +1,40 @@ +load(); + $dotenv->required(['DB_HOST', 'DB_NAME', 'DB_USER', 'DB_PASS']); + } + + $db_host = getenv('DB_HOST'); + $db_name = getenv('DB_NAME'); + $db_user = getenv('DB_USER'); + $db_pass = getenv('DB_PASS'); + $db_port = getenv('DB_PORT') ?: NULL; + + // uDb connection + if (self::$udb == null) { + self::$udb = new ReflectionClass("uDb"); + $dbInstance = self::$udb->getProperty('instance'); + $dbInstance->setAccessible(true); + $dbInstance->setValue(new uDb($db_host, $db_user, $db_pass, $db_name, $db_port)); + } + } + + public static function tearDownAfterClass() { + parent::tearDownAfterClass(); + self::$udb = null; + } +} +?> diff --git a/.tests/phpunit.xml b/.tests/phpunit.xml new file mode 100644 index 0000000..acdbf15 --- /dev/null +++ b/.tests/phpunit.xml @@ -0,0 +1,20 @@ + + + + + tests + + + + + .. + + ../.tests + ../vendor + + + + + + + diff --git a/.tests/tests/AuthTest.php b/.tests/tests/AuthTest.php new file mode 100644 index 0000000..9b56d8d --- /dev/null +++ b/.tests/tests/AuthTest.php @@ -0,0 +1,158 @@ +addTestUser($this->testUser, password_hash($this->testPass, PASSWORD_DEFAULT)); + $this->assertEquals(1, $this->getConnection()->getRowCount('users'), "Wrong row count"); + + $_REQUEST = $this->request($this->testUser, $this->testPass); + + $auth = new uAuth(); + $this->assertTrue($auth->isAuthenticated(), "Not authenticated"); + $this->assertTrue($auth->isLoginAttempt(), "Not login attempt"); + $this->assertTrue($auth->user instanceof uUser, "User variable not set"); + $this->assertEquals($this->testUser, $auth->user->login, "Wrong login"); + $this->assertEquals($_SESSION["user"]->login, $auth->user->login, "Wrong login"); + $this->assertTrue($_SESSION["user"] instanceof uUser, "User not set in session"); + } + + /** + * @runInSeparateProcess + */ + public function testLoginBadPass() { + $this->addTestUser($this->testUser, password_hash($this->testPass, PASSWORD_DEFAULT)); + $this->assertEquals(1, $this->getConnection()->getRowCount('users'), "Wrong row count"); + + $_REQUEST = $this->request($this->testUser, "badPass"); + + $auth = new uAuth(); + $this->assertFalse($auth->isAuthenticated(), "Should not be authenticated"); + $this->assertTrue($auth->isLoginAttempt(), "Not login attempt"); + $this->assertTrue(is_null($auth->user), "User not null"); + } + + /** + * @runInSeparateProcess + */ + public function testLoginEmptyLogin() { + $this->addTestUser($this->testUser, password_hash($this->testPass, PASSWORD_DEFAULT)); + $this->assertEquals(1, $this->getConnection()->getRowCount('users'), "Wrong row count"); + + $_REQUEST = $this->request("", $this->testPass); + + $auth = new uAuth(); + $this->assertFalse($auth->isAuthenticated(), "Should not be authenticated"); + $this->assertTrue($auth->isLoginAttempt(), "Not login attempt"); + $this->assertTrue(is_null($auth->user), "User not null"); + } + + /** + * @runInSeparateProcess + */ + public function testLoginNoFormData() { + $this->addTestUser($this->testUser, password_hash($this->testPass, PASSWORD_DEFAULT)); + $this->assertEquals(1, $this->getConnection()->getRowCount('users'), "Wrong row count"); + + $auth = new uAuth(); + $this->assertFalse($auth->isAuthenticated(), "Should not be authenticated"); + $this->assertFalse($auth->isLoginAttempt(), "Should not be login attempt"); + $this->assertTrue(is_null($auth->user), "User not null"); + } + + /** + * @runInSeparateProcess + */ + public function testSessionAuth() { + $this->addTestUser($this->testUser, password_hash($this->testPass, PASSWORD_DEFAULT)); + $this->assertEquals(1, $this->getConnection()->getRowCount('users'), "Wrong row count"); + + $user = new uUser($this->testUser); + $this->assertTrue($user->isValid, "User not valid"); + session_name("ulogger"); + session_start(); + $_SESSION["user"] = $user; + unset($user); + + @$auth = new uAuth(); + $this->assertTrue($auth->isAuthenticated(), "Should be authenticated"); + $this->assertFalse($auth->isLoginAttempt(), "Should not be login attempt"); + $this->assertEquals($this->testUser, $auth->user->login, "Wrong login"); + } + + /** + * @runInSeparateProcess + */ + public function testSessionAndRequest() { + $this->addTestUser($this->testUser, password_hash($this->testPass, PASSWORD_DEFAULT)); + $this->assertEquals(1, $this->getConnection()->getRowCount('users'), "Wrong row count"); + + $_REQUEST = $this->request($this->testUser, $this->testPass); + + $user = new uUser($this->testUser); + $this->assertTrue($user->isValid, "User not valid"); + session_name("ulogger"); + session_start(); + $_SESSION["user"] = $user; + unset($user); + + @$auth = new uAuth(); + $this->assertTrue($auth->isAuthenticated(), "Should be authenticated"); + $this->assertFalse($auth->isLoginAttempt(), "Should not be login attempt"); + $this->assertEquals($this->testUser, $auth->user->login, "Wrong login"); + } + + + /** + * @runInSeparateProcess + */ + public function testNotIsAdmin() { + $this->addTestUser($this->testUser, password_hash($this->testPass, PASSWORD_DEFAULT)); + $this->assertEquals(1, $this->getConnection()->getRowCount('users'), "Wrong row count"); + + $_REQUEST = $this->request($this->testUser, $this->testPass); + + @$auth = new uAuth(); + $this->assertTrue($auth->isAuthenticated(), "Should be authenticated"); + $this->assertFalse($auth->isAdmin(), "Should not be admin"); + } + + /** + * @runInSeparateProcess + */ + public function testIsAdmin() { + $this->addTestUser($this->testUser, password_hash($this->testPass, PASSWORD_DEFAULT)); + $this->assertEquals(1, $this->getConnection()->getRowCount('users'), "Wrong row count"); + + uConfig::$admin_user = $this->testUser; + $_REQUEST = $this->request($this->testUser, $this->testPass); + + @$auth = new uAuth(); + $this->assertTrue($auth->isAuthenticated(), "Should be authenticated"); + $this->assertTrue($auth->isAdmin(), "Should not be admin"); + } + +} +?> diff --git a/.tests/tests/ClientAPITest.php b/.tests/tests/ClientAPITest.php new file mode 100644 index 0000000..0ccd670 --- /dev/null +++ b/.tests/tests/ClientAPITest.php @@ -0,0 +1,379 @@ +assertTrue($this->authenticate(), "Authentication failed"); + $options = [ + 'http_errors' => false + ]; + $response = $this->http->post('/client/index.php', $options); + $this->assertEquals(200, $response->getStatusCode(), "Unexpected status code"); + $json = json_decode((string) $response->getBody()); + $this->assertTrue($json->{'error'}, "Unexpected success"); + } + + /* auth */ + + public function testAuthOk() { + $options = [ + 'http_errors' => false, + 'form_params' => [ 'action' => 'auth', 'user' => $this->testAdminUser, 'pass' => $this->testAdminPass ], + ]; + + $response = $this->http->post('/client/index.php', $options); + $this->assertEquals(200, $response->getStatusCode(), "Unexpected status code"); + $json = json_decode((string) $response->getBody()); + $this->assertFalse($json->{'error'}, "Unexpected error"); + } + + public function testAuthFail() { + $options = [ + 'http_errors' => false, + 'form_params' => [ 'action' => 'adduser', 'user' => 'noexist', 'pass' => 'noexist' ], + ]; + + $response = $this->http->post('/client/index.php', $options); + $this->assertEquals(401, $response->getStatusCode(), "Unexpected status code"); + } + + /* adduser */ + + public function testAddUser() { + $this->assertTrue($this->authenticate(), "Authentication failed"); + + $this->assertEquals(1, $this->getConnection()->getRowCount('users'), "Wrong row count"); + + $options = [ + 'http_errors' => false, + 'form_params' => [ 'action' => 'adduser', 'login' => $this->testUser, 'password' => $this->testPass ], + ]; + $response = $this->http->post('/client/index.php', $options); + $this->assertEquals(200, $response->getStatusCode(), "Unexpected status code"); + $json = json_decode((string) $response->getBody()); + $this->assertFalse($json->{'error'}, "Unexpected error"); + $this->assertEquals(2, $json->{'userid'}, "Wrong user id"); + $this->assertEquals(2, $this->getConnection()->getRowCount('users'), "Wrong row count"); + $expected = [ "id" => 2, "login" => $this->testUser ]; + $actual = $this->getConnection()->createQueryTable("users", "SELECT id, login FROM users"); + $this->assertTableContains($expected, $actual, "Wrong actual table data"); + } + + public function testAddUserExistingLogin() { + $this->assertTrue($this->authenticate(), "Authentication failed"); + + $this->assertEquals(1, $this->getConnection()->getRowCount('users'), "Wrong row count"); + + $options = [ + 'http_errors' => false, + 'form_params' => [ 'action' => 'adduser', 'login' => $this->testAdminUser, 'password' => $this->testPass ], + ]; + $response = $this->http->post('/client/index.php', $options); + $this->assertEquals(200, $response->getStatusCode(), "Unexpected status code"); + $json = json_decode((string) $response->getBody()); + $this->assertTrue($json->{'error'}, "Unexpected success"); + $this->assertFalse(isset($json->{'userid'}), "Unexpected user id"); + $this->assertEquals(1, $this->getConnection()->getRowCount('users'), "Wrong row count"); + } + + public function testAddUserEmptyLogin() { + $this->assertTrue($this->authenticate(), "Authentication failed"); + + $this->assertEquals(1, $this->getConnection()->getRowCount('users'), "Wrong row count"); + + $options = [ + 'http_errors' => false, + 'form_params' => [ 'action' => 'adduser', 'login' => '', 'password' => $this->testPass ], + ]; + $response = $this->http->post('/client/index.php', $options); + $this->assertEquals(200, $response->getStatusCode(), "Unexpected status code"); + $json = json_decode((string) $response->getBody()); + $this->assertTrue($json->{'error'}, "Unexpected success"); + $this->assertFalse(isset($json->{'userid'}), "Unexpected user id"); + $this->assertEquals(1, $this->getConnection()->getRowCount('users'), "Wrong row count"); + } + + public function testAddUserEmptyPass() { + $this->assertTrue($this->authenticate(), "Authentication failed"); + + $this->assertEquals(1, $this->getConnection()->getRowCount('users'), "Wrong row count"); + + $options = [ + 'http_errors' => false, + 'form_params' => [ 'action' => 'adduser', 'login' => $this->testUser, 'password' => '' ], + ]; + $response = $this->http->post('/client/index.php', $options); + $this->assertEquals(200, $response->getStatusCode(), "Unexpected status code"); + $json = json_decode((string) $response->getBody()); + $this->assertTrue($json->{'error'}, "Unexpected success"); + $this->assertFalse(isset($json->{'userid'}), "Unexpected user id"); + $this->assertEquals(1, $this->getConnection()->getRowCount('users'), "Wrong row count"); + } + + public function testAddUserNoParameters() { + $this->assertTrue($this->authenticate(), "Authentication failed"); + + $this->assertEquals(1, $this->getConnection()->getRowCount('users'), "Wrong row count"); + + $options = [ + 'http_errors' => false, + 'form_params' => [ 'action' => 'adduser' ], + ]; + $response = $this->http->post('/client/index.php', $options); + $this->assertEquals(200, $response->getStatusCode(), "Unexpected status code"); + $json = json_decode((string) $response->getBody()); + $this->assertTrue($json->{'error'}, "Unexpected success"); + $this->assertFalse(isset($json->{'userid'}), "Unexpected user id"); + $this->assertEquals(1, $this->getConnection()->getRowCount('users'), "Wrong row count"); + } + + public function testAddUserByNonAdmin() { + $this->addTestUser($this->testUser, password_hash($this->testPass, PASSWORD_DEFAULT)); + $this->assertTrue($this->authenticate($this->testUser, $this->testPass), "Authentication failed"); + + $this->assertEquals(2, $this->getConnection()->getRowCount('users'), "Wrong row count"); + + $options = [ + 'http_errors' => false, + 'form_params' => [ 'action' => 'adduser', 'login' => $this->testUser2, 'password' => $this->testPass ], + ]; + $response = $this->http->post('/client/index.php', $options); + $this->assertEquals(200, $response->getStatusCode(), "Unexpected status code"); + $json = json_decode((string) $response->getBody()); + $this->assertTrue($json->{'error'}, "Unexpected success"); + $this->assertFalse(isset($json->{'userid'}), "Unexpected user id"); + $this->assertEquals(2, $this->getConnection()->getRowCount('users'), "Wrong row count"); + } + + /* addtrack */ + + public function testAddTrack() { + $this->assertTrue($this->authenticate(), "Authentication failed"); + + $this->assertEquals(0, $this->getConnection()->getRowCount('tracks'), "Wrong row count"); + + $options = [ + 'http_errors' => false, + 'form_params' => [ 'action' => 'addtrack', 'track' => $this->testTrackName ], + ]; + $response = $this->http->post('/client/index.php', $options); + $this->assertEquals(200, $response->getStatusCode(), "Unexpected status code"); + $json = json_decode((string) $response->getBody()); + $this->assertFalse($json->{'error'}, "Unexpected error"); + $this->assertEquals(1, $json->{'trackid'}, "Wrong track id"); + $this->assertEquals(1, $this->getConnection()->getRowCount('tracks'), "Wrong row count"); + $expected = [ "id" => 1, "user_id" => 1, "name" => $this->testTrackName ]; + $actual = $this->getConnection()->createQueryTable("users", "SELECT id, user_id, name FROM tracks"); + $this->assertTableContains($expected, $actual, "Wrong actual table data"); + } + + public function testAddTrackEmptyName() { + $this->assertTrue($this->authenticate(), "Authentication failed"); + + $this->assertEquals(0, $this->getConnection()->getRowCount('tracks'), "Wrong row count"); + + $options = [ + 'http_errors' => false, + 'form_params' => [ 'action' => 'addtrack', 'track' => '' ], + ]; + $response = $this->http->post('/client/index.php', $options); + $this->assertEquals(200, $response->getStatusCode(), "Unexpected status code"); + $json = json_decode((string) $response->getBody()); + $this->assertTrue($json->{'error'}, "Unexpected success"); + $this->assertFalse(isset($json->{'trackid'}), "Unexpected track id"); + $this->assertEquals(0, $this->getConnection()->getRowCount('tracks'), "Wrong row count"); + } + + public function testAddTrackNoParameters() { + $this->assertTrue($this->authenticate(), "Authentication failed"); + + $this->assertEquals(0, $this->getConnection()->getRowCount('tracks'), "Wrong row count"); + + $options = [ + 'http_errors' => false, + 'form_params' => [ 'action' => 'addtrack' ], + ]; + $response = $this->http->post('/client/index.php', $options); + $this->assertEquals(200, $response->getStatusCode(), "Unexpected status code"); + $json = json_decode((string) $response->getBody()); + $this->assertTrue($json->{'error'}, "Unexpected success"); + $this->assertFalse(isset($json->{'trackid'}), "Unexpected track id"); + $this->assertEquals(0, $this->getConnection()->getRowCount('tracks'), "Wrong row count"); + } + + /* addpos */ + + public function testAddPosition() { + $this->assertTrue($this->authenticate(), "Authentication failed"); + + $trackId = $this->addTestTrack($this->testUserId); + $this->assertEquals(1, $this->getConnection()->getRowCount('tracks'), "Wrong row count"); + $this->assertEquals(0, $this->getConnection()->getRowCount('positions'), "Wrong row count"); + + $options = [ + 'http_errors' => false, + 'form_params' => [ + 'action' => 'addpos', + 'trackid' => $trackId, + 'time' => $this->testTimestamp, + 'lat' => $this->testLat, + 'lon' => $this->testLon, + 'altitude' => $this->testAltitude, + 'speed' => $this->testSpeed, + 'bearing' => $this->testBearing, + 'accuracy' => $this->testAccuracy, + 'provider' => $this->testProvider, + 'comment' => $this->testComment, + 'imageid' => $this->testImageId + ], + ]; + $response = $this->http->post('/client/index.php', $options); + $this->assertEquals(200, $response->getStatusCode(), "Unexpected status code"); + $json = json_decode((string) $response->getBody()); + $this->assertFalse($json->{'error'}, "Unexpected error"); + $this->assertEquals(1, $this->getConnection()->getRowCount('positions'), "Wrong row count"); + $expected = [ + "id" => 1, + "user_id" => $this->testUserId, + "track_id" => $trackId, + "time" => $this->testTimestamp, + "latitude" => $this->testLat, + "longitude" => $this->testLon, + "altitude" => $this->testAltitude, + "speed" => $this->testSpeed, + "bearing" => $this->testBearing, + "accuracy" => $this->testAccuracy, + "provider" => $this->testProvider, + "comment" => $this->testComment, + "image_id" => $this->testImageId + ]; + $actual = $this->getConnection()->createQueryTable( + "positions", + "SELECT id, user_id, track_id, UNIX_TIMESTAMP(time) AS time, latitude, longitude, altitude, speed, bearing, accuracy, provider, comment, image_id FROM positions" + ); + $this->assertTableContains($expected, $actual, "Wrong actual table data"); + } + + public function testAddPositionNoexistantTrack() { + $this->assertTrue($this->authenticate(), "Authentication failed"); + + $this->assertEquals(0, $this->getConnection()->getRowCount('tracks'), "Wrong row count"); + $this->assertEquals(0, $this->getConnection()->getRowCount('positions'), "Wrong row count"); + + $options = [ + 'http_errors' => false, + 'form_params' => [ + 'action' => 'addpos', + 'trackid' => $this->testTrackId, + 'time' => $this->testTimestamp, + 'lat' => $this->testLat, + 'lon' => $this->testLon, + 'altitude' => $this->testAltitude, + 'speed' => $this->testSpeed, + 'bearing' => $this->testBearing, + 'accuracy' => $this->testAccuracy, + 'provider' => $this->testProvider, + 'comment' => $this->testComment, + 'imageid' => $this->testImageId + ], + ]; + $response = $this->http->post('/client/index.php', $options); + $this->assertEquals(200, $response->getStatusCode(), "Unexpected status code"); + $json = json_decode((string) $response->getBody()); + $this->assertTrue($json->{'error'}, "Unexpected success"); + $this->assertEquals(0, $this->getConnection()->getRowCount('positions'), "Wrong row count"); + } + + public function testAddPositionEmptyParameters() { + $this->assertTrue($this->authenticate(), "Authentication failed"); + + $trackId = $this->addTestTrack($this->testUserId); + $this->assertEquals(1, $this->getConnection()->getRowCount('tracks'), "Wrong row count"); + $this->assertEquals(0, $this->getConnection()->getRowCount('positions'), "Wrong row count"); + + $options = [ + 'http_errors' => false, + 'form_params' => [ + 'action' => 'addpos', + 'trackid' => $trackId, + 'time' => $this->testTimestamp, + 'lat' => $this->testLat, + 'lon' => $this->testLon, + 'altitude' => $this->testAltitude, + 'speed' => $this->testSpeed, + 'bearing' => $this->testBearing, + 'accuracy' => $this->testAccuracy, + 'provider' => $this->testProvider, + 'comment' => $this->testComment, + 'imageid' => $this->testImageId + ], + ]; + + // required + foreach ([ 'trackid', 'time', 'lat', 'lon' ] as $parameter) { + $optCopy = $options; + $optCopy['form_params'][$parameter] = ''; + $response = $this->http->post('/client/index.php', $optCopy); + $this->assertEquals(200, $response->getStatusCode(), "Unexpected status code"); + $json = json_decode((string) $response->getBody()); + $this->assertTrue($json->{'error'}, "Unexpected success ($parameter)"); + } + $this->assertEquals(0, $this->getConnection()->getRowCount('positions'), "Wrong row count"); + } + + public function testAddPositionMissingParameters() { + $this->assertTrue($this->authenticate(), "Authentication failed"); + + $trackId = $this->addTestTrack($this->testUserId); + $this->assertEquals(1, $this->getConnection()->getRowCount('tracks'), "Wrong row count"); + $this->assertEquals(0, $this->getConnection()->getRowCount('positions'), "Wrong row count"); + + $options = [ + 'http_errors' => false, + 'form_params' => [ + 'action' => 'addpos', + 'trackid' => $trackId, + 'time' => $this->testTimestamp, + 'lat' => $this->testLat, + 'lon' => $this->testLon, + 'altitude' => $this->testAltitude, + 'speed' => $this->testSpeed, + 'bearing' => $this->testBearing, + 'accuracy' => $this->testAccuracy, + 'provider' => $this->testProvider, + 'comment' => $this->testComment, + 'imageid' => $this->testImageId + ], + ]; + + // required + foreach ([ 'trackid', 'time', 'lat', 'lon' ] as $parameter) { + $optCopy = $options; + unset($optCopy['form_params'][$parameter]); + $response = $this->http->post('/client/index.php', $optCopy); + $this->assertEquals(200, $response->getStatusCode(), "Unexpected status code"); + $json = json_decode((string) $response->getBody()); + $this->assertTrue($json->{'error'}, "Unexpected success ($parameter)"); + } + $this->assertEquals(0, $this->getConnection()->getRowCount('positions'), "Wrong row count"); + + // optional + $optional = [ 'altitude', 'speed', 'bearing', 'accuracy', 'provider', 'comment', 'imageid' ]; + foreach ($optional as $parameter) { + $optCopy = $options; + unset($optCopy['form_params'][$parameter]); + $response = $this->http->post('/client/index.php', $optCopy); + $this->assertEquals(200, $response->getStatusCode(), "Unexpected status code"); + $json = json_decode((string) $response->getBody()); + $this->assertFalse($json->{'error'}, "Unexpected error ($parameter)"); + } + $this->assertEquals(count($optional), $this->getConnection()->getRowCount('positions'), "Wrong row count"); + + } + + +} + +?> diff --git a/.tests/tests/ConfigTest.php b/.tests/tests/ConfigTest.php new file mode 100644 index 0000000..806cde7 --- /dev/null +++ b/.tests/tests/ConfigTest.php @@ -0,0 +1,62 @@ +assertRegExp($regex, $password0, "Regex: \"$regex\", password: \"$password0\""); + $this->assertRegExp($regex, $password1, "Regex: \"$regex\", password: \"$password1\""); + $this->assertRegExp($regex, $password2, "Regex: \"$regex\", password: \"$password2\""); + $this->assertRegExp($regex, $password3, "Regex: \"$regex\", password: \"$password3\""); + + uConfig::$pass_strength = 1; + $regex = uConfig::passRegex(); + $this->assertNotRegExp($regex, $password0, "Regex: \"$regex\", password: \"$password0\""); + $this->assertRegExp($regex, $password1, "Regex: \"$regex\", password: \"$password1\""); + $this->assertRegExp($regex, $password2, "Regex: \"$regex\", password: \"$password2\""); + $this->assertRegExp($regex, $password3, "Regex: \"$regex\", password: \"$password3\""); + + uConfig::$pass_strength = 2; + $regex = uConfig::passRegex(); + $this->assertNotRegExp($regex, $password0, "Regex: \"$regex\", password: \"$password0\""); + $this->assertNotRegExp($regex, $password1, "Regex: \"$regex\", password: \"$password1\""); + $this->assertRegExp($regex, $password2, "Regex: \"$regex\", password: \"$password2\""); + $this->assertRegExp($regex, $password3, "Regex: \"$regex\", password: \"$password3\""); + + uConfig::$pass_strength = 3; + $regex = uConfig::passRegex(); + $this->assertNotRegExp($regex, $password0, "Regex: \"$regex\", password: \"$password0\""); + $this->assertNotRegExp($regex, $password1, "Regex: \"$regex\", password: \"$password1\""); + $this->assertNotRegExp($regex, $password2, "Regex: \"$regex\", password: \"$password2\""); + $this->assertRegExp($regex, $password3, "Regex: \"$regex\", password: \"$password3\""); + + $password_len5 = "12345"; + $password_len10 = "1234567890"; + uConfig::$pass_lenmin = 5; + uConfig::$pass_strength = 0; + $regex = uConfig::passRegex(); + $this->assertRegExp($regex, $password_len5, "Regex: \"$regex\", password: \"$password_len5\""); + $this->assertRegExp($regex, $password_len10, "Regex: \"$regex\", password: \"$password_len10\""); + + uConfig::$pass_lenmin = 7; + $regex = uConfig::passRegex(); + $this->assertNotRegExp($regex, $password_len5, "Regex: \"$regex\", password: \"$password_len5\""); + $this->assertRegExp($regex, $password_len10, "Regex: \"$regex\", password: \"$password_len10\""); + + uConfig::$pass_lenmin = 12; + $regex = uConfig::passRegex(); + $this->assertNotRegExp($regex, $password_len5, "Regex: \"$regex\", password: \"$password_len5\""); + $this->assertNotRegExp($regex, $password_len10, "Regex: \"$regex\", password: \"$password_len10\""); + } +} +?> diff --git a/.tests/tests/PositionTest.php b/.tests/tests/PositionTest.php new file mode 100644 index 0000000..21bcce3 --- /dev/null +++ b/.tests/tests/PositionTest.php @@ -0,0 +1,143 @@ +addTestTrack($this->testUserId); + $this->assertEquals(1, $this->getConnection()->getRowCount('tracks'), "Wrong row count"); + + $posId = uPosition::add($this->testUserId, $trackId + 1, $this->testTimestamp, $this->testLat, $this->testLon, $this->testAltitude, $this->testSpeed, $this->testBearing, $this->testAccuracy, $this->testProvider, $this->testComment, $this->testImageId); + $this->assertEquals(0, $this->getConnection()->getRowCount('positions'), "Wrong row count"); + $this->assertFalse($posId, "Adding position with nonexistant track should fail"); + + $posId = uPosition::add($this->testUserId2, $trackId, $this->testTimestamp, $this->testLat, $this->testLon, $this->testAltitude, $this->testSpeed, $this->testBearing, $this->testAccuracy, $this->testProvider, $this->testComment, $this->testImageId); + $this->assertEquals(0, $this->getConnection()->getRowCount('positions'), "Wrong row count"); + $this->assertFalse($posId, "Adding position with wrong user should fail"); + + $posId = uPosition::add($this->testUserId, $trackId, $this->testTimestamp, $this->testLat, $this->testLon, $this->testAltitude, $this->testSpeed, $this->testBearing, $this->testAccuracy, $this->testProvider, $this->testComment, $this->testImageId); + $this->assertEquals(1, $this->getConnection()->getRowCount('positions'), "Wrong row count"); + $expected = [ + "id" => $posId, + "user_id" => $this->testUserId, + "track_id" => $trackId, + "time" => $this->testTimestamp, + "latitude" => $this->testLat, + "longitude" => $this->testLon, + "altitude" => $this->testAltitude, + "speed" => $this->testSpeed, + "bearing" => $this->testBearing, + "accuracy" => $this->testAccuracy, + "provider" => $this->testProvider, + "comment" => $this->testComment, + "image_id" => $this->testImageId + ]; + $actual = $this->getConnection()->createQueryTable( + "positions", + "SELECT id, user_id, track_id, UNIX_TIMESTAMP(time) AS time, latitude, longitude, altitude, speed, bearing, accuracy, provider, comment, image_id FROM positions" + ); + $this->assertTableContains($expected, $actual, "Wrong actual table data"); + + $posId = uPosition::add($this->testUserId, $trackId, NULL, $this->testLat, $this->testLon); + $this->assertFalse($posId, "Adding position with null time stamp should fail"); + $posId = uPosition::add($this->testUserId, $trackId, $this->testTimestamp, NULL, $this->testLon); + $this->assertFalse($posId, "Adding position with null latitude should fail"); + $posId = uPosition::add($this->testUserId, $trackId, $this->testTimestamp, $this->testLat, NULL); + $this->assertFalse($posId, "Adding position with null longitude should fail"); + + $posId = uPosition::add($this->testUserId, $trackId, "", $this->testLat, $this->testLon); + $this->assertFalse($posId, "Adding position with empty time stamp should fail"); + $posId = uPosition::add($this->testUserId, $trackId, $this->testTimestamp, "", $this->testLon); + $this->assertFalse($posId, "Adding position with empty latitude should fail"); + $posId = uPosition::add($this->testUserId, $trackId, $this->testTimestamp, $this->testLat, ""); + $this->assertFalse($posId, "Adding position with empty longitude should fail"); + } + + public function testDeleteAll() { + $trackId = $this->addTestTrack($this->testUserId); + $this->addTestPosition($this->testUserId, $trackId); + $trackId2 = $this->addTestTrack($this->testUserId); + $this->addTestPosition($this->testUserId, $trackId2); + $trackId3 = $this->addTestTrack($this->testUserId2); + $this->addTestPosition($this->testUserId2, $trackId3); + $this->assertEquals(3, $this->getConnection()->getRowCount('tracks'), "Wrong row count"); + $this->assertEquals(3, $this->getConnection()->getRowCount('positions'), "Wrong row count"); + + $this->assertTrue(uPosition::deleteAll($this->testUserId), "Deleting failed"); + $this->assertEquals(1, $this->getConnection()->getRowCount('positions'), "Wrong row count"); + } + + public function testDeleteAllWIthTrackId() { + $trackId = $this->addTestTrack($this->testUserId); + $this->addTestPosition($this->testUserId, $trackId); + $trackId2 = $this->addTestTrack($this->testUserId); + $this->addTestPosition($this->testUserId, $trackId2); + $trackId3 = $this->addTestTrack($this->testUserId2); + $this->addTestPosition($this->testUserId2, $trackId3); + $this->assertEquals(3, $this->getConnection()->getRowCount('tracks'), "Wrong row count"); + $this->assertEquals(3, $this->getConnection()->getRowCount('positions'), "Wrong row count"); + + $this->assertTrue(uPosition::deleteAll($this->testUserId, $trackId), "Deleting failed"); + $this->assertEquals(2, $this->getConnection()->getRowCount('positions'), "Wrong row count"); + } + + public function testGetLast() { + $trackId1 = $this->addTestTrack($this->testUserId); + $trackId2 = $this->addTestTrack($this->testUserId); + $pos1 = $this->addTestPosition($this->testUserId, $trackId1, $this->testTimestamp + 3); + $pos2 = $this->addTestPosition($this->testUserId2, $trackId2, $this->testTimestamp + 1); + $pos3 = $this->addTestPosition($this->testUserId, $trackId1, $this->testTimestamp); + $pos4 = $this->addTestPosition($this->testUserId2, $trackId2, $this->testTimestamp + 2); + $this->assertEquals(2, $this->getConnection()->getRowCount('tracks'), "Wrong row count"); + $this->assertEquals(4, $this->getConnection()->getRowCount('positions'), "Wrong row count"); + $lastPosition = uPosition::getLast(); + $this->assertEquals($lastPosition->id, $pos1, "Wrong last position"); + $lastPosition = uPosition::getLast($this->testUserId2); + $this->assertEquals($lastPosition->id, $pos4, "Wrong last position (user)"); + } + + public function testGetAll() { + $trackId = $this->addTestTrack($this->testUserId); + $this->addTestPosition($this->testUserId, $trackId); + $trackId2 = $this->addTestTrack($this->testUserId); + $this->addTestPosition($this->testUserId, $trackId2); + $trackId3 = $this->addTestTrack($this->testUserId2); + $this->addTestPosition($this->testUserId2, $trackId3); + $this->assertEquals(3, $this->getConnection()->getRowCount('tracks'), "Wrong row count"); + $this->assertEquals(3, $this->getConnection()->getRowCount('positions'), "Wrong row count"); + + $posArr = uPosition::getAll(); + $this->assertEquals(3, count($posArr), "Wrong row count"); + $posArr = uPosition::getAll($this->testUserId); + $this->assertEquals(2, count($posArr), "Wrong row count"); + $posArr = uPosition::getAll($this->testUserId, $trackId); + $this->assertEquals(1, count($posArr), "Wrong row count"); + $posArr = uPosition::getAll(NULL, $trackId); + $this->assertEquals(1, count($posArr), "Wrong row count"); + $posArr = uPosition::getAll($this->testUserId3); + $this->assertEquals(0, count($posArr), "Wrong row count"); + } + + public function testDistanceTo() { + $trackId = $this->addTestTrack($this->testUserId); + $pos1 = $this->addTestPosition($this->testUserId, $trackId, $this->testTimestamp, 0, 0); + $pos2 = $this->addTestPosition($this->testUserId, $trackId, $this->testTimestamp, 0, 1); + $posArr = uPosition::getAll(); + $this->assertEquals(2, count($posArr), "Wrong row count"); + $this->assertEquals(111195, round($posArr[0]->distanceTo($posArr[1])), "Wrong distance"); + } + + public function testSecondsTo() { + $trackId = $this->addTestTrack($this->testUserId); + $pos1 = $this->addTestPosition($this->testUserId, $trackId, $this->testTimestamp); + $pos2 = $this->addTestPosition($this->testUserId, $trackId, $this->testTimestamp + 1); + $posArr = uPosition::getAll(); + $this->assertEquals(2, count($posArr), "Wrong row count"); + $this->assertEquals(-1, $posArr[0]->secondsTo($posArr[1]), "Wrong time difference"); + } + +} +?> diff --git a/.tests/tests/TrackTest.php b/.tests/tests/TrackTest.php new file mode 100644 index 0000000..3ae563c --- /dev/null +++ b/.tests/tests/TrackTest.php @@ -0,0 +1,133 @@ +testUserId, $this->testTrackName, $this->testTrackComment); + $this->assertEquals(1, $this->getConnection()->getRowCount('tracks'), "Wrong row count"); + $this->assertEquals(1, $trackId, "Wrong track id returned"); + $expected = [ "id" => $trackId, "user_id" => $this->testUserId, "name" => $this->testTrackName, "comment" => $this->testTrackComment ]; + $actual = $this->getConnection()->createQueryTable("tracks", "SELECT id, user_id, name, comment FROM tracks"); + $this->assertTableContains($expected, $actual, "Wrong actual table data"); + + $this->assertFalse(uTrack::add("", $this->testTrackName), "Adding track with empty user id should fail"); + $this->assertFalse(uTrack::add($this->testUserId, ""), "Adding track with empty name should fail"); + } + + public function testDeleteTrack() { + $trackId = $this->addTestTrack($this->testUserId); + $this->addTestPosition($this->testUserId, $trackId); + $this->assertEquals(1, $this->getConnection()->getRowCount('tracks'), "Wrong row count"); + $this->assertEquals(1, $this->getConnection()->getRowCount('positions'), "Wrong row count"); + + $track = new uTrack($trackId); + $track->delete(); + $this->assertEquals(0, $this->getConnection()->getRowCount('tracks'), "Wrong row count"); + $this->assertEquals(0, $this->getConnection()->getRowCount('positions'), "Wrong row count"); + $this->assertFalse($track->isValid, "Deleted track should not be valid"); + } + + public function testAddPosition() { + $trackId = $this->addTestTrack($this->testUserId); + $this->assertEquals(1, $this->getConnection()->getRowCount('tracks'), "Wrong row count"); + + $track = new uTrack($trackId + 1); + $posId = $track->addPosition($this->testUserId, $this->testTimestamp, $this->testLat, $this->testLon, $this->testAltitude, $this->testSpeed, $this->testBearing, $this->testAccuracy, $this->testProvider, $this->testComment, $this->testImageId); + $this->assertEquals(0, $this->getConnection()->getRowCount('positions'), "Wrong row count"); + $this->assertFalse($posId, "Adding position with nonexistant track should fail"); + + $track = new uTrack($trackId); + $posId = $track->addPosition($this->testUserId2, $this->testTimestamp, $this->testLat, $this->testLon, $this->testAltitude, $this->testSpeed, $this->testBearing, $this->testAccuracy, $this->testProvider, $this->testComment, $this->testImageId); + $this->assertEquals(0, $this->getConnection()->getRowCount('positions'), "Wrong row count"); + $this->assertFalse($posId, "Adding position with wrong user should fail"); + + $posId = $track->addPosition($this->testUserId, $this->testTimestamp, $this->testLat, $this->testLon, $this->testAltitude, $this->testSpeed, $this->testBearing, $this->testAccuracy, $this->testProvider, $this->testComment, $this->testImageId); + $this->assertEquals(1, $this->getConnection()->getRowCount('positions'), "Wrong row count"); + $expected = [ + "id" => $posId, + "user_id" => $this->testUserId, + "track_id" => $trackId, + "time" => $this->testTimestamp, + "latitude" => $this->testLat, + "longitude" => $this->testLon, + "altitude" => $this->testAltitude, + "speed" => $this->testSpeed, + "bearing" => $this->testBearing, + "accuracy" => $this->testAccuracy, + "provider" => $this->testProvider, + "comment" => $this->testComment, + "image_id" => $this->testImageId + ]; + $actual = $this->getConnection()->createQueryTable( + "positions", + "SELECT id, user_id, track_id, UNIX_TIMESTAMP(time) AS time, latitude, longitude, altitude, speed, bearing, accuracy, provider, comment, image_id FROM positions" + ); + $this->assertTableContains($expected, $actual, "Wrong actual table data"); + + $posId = $track->addPosition($this->testUserId, NULL, $this->testLat, $this->testLon); + $this->assertFalse($posId, "Adding position with null time stamp should fail"); + $posId = $track->addPosition($this->testUserId, $this->testTimestamp, NULL, $this->testLon); + $this->assertFalse($posId, "Adding position with null latitude should fail"); + $posId = $track->addPosition($this->testUserId, $this->testTimestamp, $this->testLat, NULL); + $this->assertFalse($posId, "Adding position with null longitude should fail"); + + $posId = $track->addPosition($this->testUserId, "", $this->testLat, $this->testLon); + $this->assertFalse($posId, "Adding position with empty time stamp should fail"); + $posId = $track->addPosition($this->testUserId, $this->testTimestamp, "", $this->testLon); + $this->assertFalse($posId, "Adding position with empty latitude should fail"); + $posId = $track->addPosition($this->testUserId, $this->testTimestamp, $this->testLat, ""); + $this->assertFalse($posId, "Adding position with empty longitude should fail"); + } + + public function testGetAll() { + $this->addTestTrack(); + $this->addTestTrack(); + $this->assertEquals(2, $this->getConnection()->getRowCount('tracks'), "Wrong row count"); + + $trackArr = uTrack::getAll(); + $this->assertEquals(2, count($trackArr), "Wrong array size"); + $this->assertTrue($trackArr[0] instanceof uTrack, "Wrong array member"); + } + + public function testDeleteAll() { + $trackId = $this->addTestTrack(); + $this->addTestTrack(); + $this->addTestPosition($this->testUserId, $trackId); + + $trackId2 = $this->addTestTrack($this->testUserId2); + $this->addTestPosition($this->testUserId2, $trackId2); + + $this->assertEquals(3, $this->getConnection()->getRowCount('tracks'), "Wrong row count"); + $this->assertEquals(2, $this->getConnection()->getRowCount('positions'), "Wrong row count"); + + uTrack::deleteAll($this->testUserId); + $this->assertEquals(1, $this->getConnection()->getRowCount('tracks'), "Wrong row count"); + $this->assertEquals(1, $this->getConnection()->getRowCount('positions'), "Wrong row count"); + $this->assertFalse(uTrack::deleteAll(NULL), "User id should not be empty"); + } + + public function testUpdate() { + $trackId = $this->addTestTrack(); + $track = new uTrack($trackId); + $track->update("newName", "newComment"); + $expected = [ "id" => $trackId, "user_id" => $this->testUserId, "name" => "newName", "comment" => "newComment" ]; + $actual = $this->getConnection()->createQueryTable("tracks", "SELECT id, user_id, name, comment FROM tracks"); + $this->assertTableContains($expected, $actual, "Wrong actual table data"); + + $trackInvalid = new uTrack($trackId + 1); + $this->assertFalse($trackInvalid->update("newName", "newComment"), "Updating nonexistant track should fail"); + } + + public function testIsValid() { + $trackId = $this->addTestTrack(); + $trackValid = new uTrack($trackId); + $this->assertTrue($trackValid->isValid, "Track should be valid"); + $trackInvalid = new uTrack($trackId + 1); + $this->assertFalse($trackInvalid->isValid, "Track should not be valid"); + } +} +?> diff --git a/.tests/tests/UserTest.php b/.tests/tests/UserTest.php new file mode 100644 index 0000000..3ba4af5 --- /dev/null +++ b/.tests/tests/UserTest.php @@ -0,0 +1,81 @@ +testUser, $this->testPass); + $this->assertEquals(1, $this->getConnection()->getRowCount('users'), "Wrong row count"); + $this->assertEquals(1, $userId, "Wrong user id returned"); + $expected = [ "id" => 1, "login" => $this->testUser ]; + $actual = $this->getConnection()->createQueryTable("users", "SELECT id, login FROM users"); + $this->assertTableContains($expected, $actual, "Wrong actual table data"); + + $this->assertTrue(password_verify($this->testPass, $this->pdoGetColumn("SELECT password FROM users")), "Wrong actual password hash"); + $this->assertFalse(uUser::add($this->testUser, $this->testPass), "Adding user with same login should fail"); + $this->assertFalse(uUser::add($this->testUser, ""), "Adding user with empty password should fail"); + $this->assertFalse(uUser::add("", $this->testPass), "Adding user with empty login should fail"); + } + + public function testDeleteUser() { + $userId = $this->addTestUser($this->testUser); + $trackId = $this->addTestTrack($userId); + $this->addTestPosition($userId, $trackId); + + $this->assertEquals(1, $this->getConnection()->getRowCount('users'), "Wrong row count"); + $this->assertEquals(1, $this->getConnection()->getRowCount('tracks'), "Wrong row count"); + $this->assertEquals(1, $this->getConnection()->getRowCount('positions'), "Wrong row count"); + + $user = new uUser($this->testUser); + $user->delete(); + $this->assertEquals(0, $this->getConnection()->getRowCount('users'), "Wrong row count"); + $this->assertEquals(0, $this->getConnection()->getRowCount('tracks'), "Wrong row count"); + $this->assertEquals(0, $this->getConnection()->getRowCount('positions'), "Wrong row count"); + $this->assertFalse($user->isValid, "Deleted user should not be valid"); + } + + public function testSetPass() { + $newPass = $this->testPass . "new"; + $this->addTestUser($this->testUser); + $this->assertEquals(1, $this->getConnection()->getRowCount('users'), "Wrong row count"); + + $user = new uUser($this->testUser); + $user->setPass($newPass); + $this->assertTrue(password_verify($newPass, $this->pdoGetColumn("SELECT password FROM users")), "Wrong actual password hash"); + $this->assertFalse($user->setPass(""), "Password should not be empty"); + + $userInvalid = new uUser($this->testUser . "-noexistant"); + $this->assertFalse($userInvalid->setPass($newPass), "Setting pass for nonexistant user should fail"); + } + + public function testGetAll() { + $this->addTestUser($this->testUser); + $this->addTestUser($this->testUser2); + $this->assertEquals(2, $this->getConnection()->getRowCount('users'), "Wrong row count"); + + $userArr = uUser::getAll(); + $this->assertEquals(2, count($userArr), "Wrong array size"); + $this->assertTrue($userArr[0] instanceof uUser, "Wrong array member"); + } + + public function testIsAdmin() { + $this->addTestUser($this->testUser); + $user = new uUser($this->testUser); + $this->assertFalse($user->isAdmin, "User should not be admin"); + uConfig::$admin_user = $this->testUser; + $user = new uUser($this->testUser); + $this->assertTrue($user->isAdmin, "User should be admin"); + } + + public function testIsValid() { + $this->addTestUser($this->testUser); + $userValid = new uUser($this->testUser); + $this->assertTrue($userValid->isValid, "User should be valid"); + $userInvalid = new uUser($this->testUser . "-noexistant"); + $this->assertFalse($userInvalid->isValid, "User should not be valid"); + } +} +?> diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 0000000..6afa12a --- /dev/null +++ b/.travis.yml @@ -0,0 +1,26 @@ +language: php + +sudo: required + +php: + - 7.0 + +env: + - DB_HOST="localhost" + - DB_NAME="ulogger" + - DB_USER="ulogger" + - DB_PASS="secret2" + - DB_PORT=8081 + - ULOGGER_URL="http://127.0.0.1:8080" + +services: + - docker + +before_install: + - docker build -t ulogger . + - docker run -d --name ulogger -p 8080:80 -p 8081:3306 --expose 3306 ulogger + - composer install + - until netstat -atn 2>/dev/null | grep '8080.*LISTEN'; do sleep 1; done + +script: + - ./vendor/bin/phpunit -c .tests/phpunit.xml \ No newline at end of file diff --git a/composer.json b/composer.json new file mode 100644 index 0000000..d8c9c56 --- /dev/null +++ b/composer.json @@ -0,0 +1,13 @@ +{ + "require": { + "phpunit/phpunit": "^5.7", + "vlucas/phpdotenv": "^2.4", + "guzzlehttp/guzzle": "^6.3" + }, + "scripts": { + "test": "./vendor/bin/phpunit" + }, + "require-dev": { + "phpunit/dbunit": "^2.0" + } +} diff --git a/composer.lock b/composer.lock new file mode 100644 index 0000000..d3e068e --- /dev/null +++ b/composer.lock @@ -0,0 +1,1668 @@ +{ + "_readme": [ + "This file locks the dependencies of your project to a known state", + "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file", + "This file is @generated automatically" + ], + "content-hash": "2d8c5cc5e1d061a121d0f1dc7a602ac4", + "packages": [ + { + "name": "doctrine/instantiator", + "version": "1.0.5", + "source": { + "type": "git", + "url": "https://github.com/doctrine/instantiator.git", + "reference": "8e884e78f9f0eb1329e445619e04456e64d8051d" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/doctrine/instantiator/zipball/8e884e78f9f0eb1329e445619e04456e64d8051d", + "reference": "8e884e78f9f0eb1329e445619e04456e64d8051d", + "shasum": "" + }, + "require": { + "php": ">=5.3,<8.0-DEV" + }, + "require-dev": { + "athletic/athletic": "~0.1.8", + "ext-pdo": "*", + "ext-phar": "*", + "phpunit/phpunit": "~4.0", + "squizlabs/php_codesniffer": "~2.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "Doctrine\\Instantiator\\": "src/Doctrine/Instantiator/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Marco Pivetta", + "email": "ocramius@gmail.com", + "homepage": "http://ocramius.github.com/" + } + ], + "description": "A small, lightweight utility to instantiate objects in PHP without invoking their constructors", + "homepage": "https://github.com/doctrine/instantiator", + "keywords": [ + "constructor", + "instantiate" + ], + "time": "2015-06-14T21:17:01+00:00" + }, + { + "name": "guzzlehttp/guzzle", + "version": "6.3.0", + "source": { + "type": "git", + "url": "https://github.com/guzzle/guzzle.git", + "reference": "f4db5a78a5ea468d4831de7f0bf9d9415e348699" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/guzzle/guzzle/zipball/f4db5a78a5ea468d4831de7f0bf9d9415e348699", + "reference": "f4db5a78a5ea468d4831de7f0bf9d9415e348699", + "shasum": "" + }, + "require": { + "guzzlehttp/promises": "^1.0", + "guzzlehttp/psr7": "^1.4", + "php": ">=5.5" + }, + "require-dev": { + "ext-curl": "*", + "phpunit/phpunit": "^4.0 || ^5.0", + "psr/log": "^1.0" + }, + "suggest": { + "psr/log": "Required for using the Log middleware" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "6.2-dev" + } + }, + "autoload": { + "files": [ + "src/functions_include.php" + ], + "psr-4": { + "GuzzleHttp\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Michael Dowling", + "email": "mtdowling@gmail.com", + "homepage": "https://github.com/mtdowling" + } + ], + "description": "Guzzle is a PHP HTTP client library", + "homepage": "http://guzzlephp.org/", + "keywords": [ + "client", + "curl", + "framework", + "http", + "http client", + "rest", + "web service" + ], + "time": "2017-06-22T18:50:49+00:00" + }, + { + "name": "guzzlehttp/promises", + "version": "v1.3.1", + "source": { + "type": "git", + "url": "https://github.com/guzzle/promises.git", + "reference": "a59da6cf61d80060647ff4d3eb2c03a2bc694646" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/guzzle/promises/zipball/a59da6cf61d80060647ff4d3eb2c03a2bc694646", + "reference": "a59da6cf61d80060647ff4d3eb2c03a2bc694646", + "shasum": "" + }, + "require": { + "php": ">=5.5.0" + }, + "require-dev": { + "phpunit/phpunit": "^4.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.4-dev" + } + }, + "autoload": { + "psr-4": { + "GuzzleHttp\\Promise\\": "src/" + }, + "files": [ + "src/functions_include.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Michael Dowling", + "email": "mtdowling@gmail.com", + "homepage": "https://github.com/mtdowling" + } + ], + "description": "Guzzle promises library", + "keywords": [ + "promise" + ], + "time": "2016-12-20T10:07:11+00:00" + }, + { + "name": "guzzlehttp/psr7", + "version": "1.4.2", + "source": { + "type": "git", + "url": "https://github.com/guzzle/psr7.git", + "reference": "f5b8a8512e2b58b0071a7280e39f14f72e05d87c" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/guzzle/psr7/zipball/f5b8a8512e2b58b0071a7280e39f14f72e05d87c", + "reference": "f5b8a8512e2b58b0071a7280e39f14f72e05d87c", + "shasum": "" + }, + "require": { + "php": ">=5.4.0", + "psr/http-message": "~1.0" + }, + "provide": { + "psr/http-message-implementation": "1.0" + }, + "require-dev": { + "phpunit/phpunit": "~4.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.4-dev" + } + }, + "autoload": { + "psr-4": { + "GuzzleHttp\\Psr7\\": "src/" + }, + "files": [ + "src/functions_include.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Michael Dowling", + "email": "mtdowling@gmail.com", + "homepage": "https://github.com/mtdowling" + }, + { + "name": "Tobias Schultze", + "homepage": "https://github.com/Tobion" + } + ], + "description": "PSR-7 message implementation that also provides common utility methods", + "keywords": [ + "http", + "message", + "request", + "response", + "stream", + "uri", + "url" + ], + "time": "2017-03-20T17:10:46+00:00" + }, + { + "name": "myclabs/deep-copy", + "version": "1.6.1", + "source": { + "type": "git", + "url": "https://github.com/myclabs/DeepCopy.git", + "reference": "8e6e04167378abf1ddb4d3522d8755c5fd90d102" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/myclabs/DeepCopy/zipball/8e6e04167378abf1ddb4d3522d8755c5fd90d102", + "reference": "8e6e04167378abf1ddb4d3522d8755c5fd90d102", + "shasum": "" + }, + "require": { + "php": ">=5.4.0" + }, + "require-dev": { + "doctrine/collections": "1.*", + "phpunit/phpunit": "~4.1" + }, + "type": "library", + "autoload": { + "psr-4": { + "DeepCopy\\": "src/DeepCopy/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "description": "Create deep copies (clones) of your objects", + "homepage": "https://github.com/myclabs/DeepCopy", + "keywords": [ + "clone", + "copy", + "duplicate", + "object", + "object graph" + ], + "time": "2017-04-12T18:52:22+00:00" + }, + { + "name": "phpdocumentor/reflection-common", + "version": "1.0", + "source": { + "type": "git", + "url": "https://github.com/phpDocumentor/ReflectionCommon.git", + "reference": "144c307535e82c8fdcaacbcfc1d6d8eeb896687c" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/phpDocumentor/ReflectionCommon/zipball/144c307535e82c8fdcaacbcfc1d6d8eeb896687c", + "reference": "144c307535e82c8fdcaacbcfc1d6d8eeb896687c", + "shasum": "" + }, + "require": { + "php": ">=5.5" + }, + "require-dev": { + "phpunit/phpunit": "^4.6" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "phpDocumentor\\Reflection\\": [ + "src" + ] + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Jaap van Otterdijk", + "email": "opensource@ijaap.nl" + } + ], + "description": "Common reflection classes used by phpdocumentor to reflect the code structure", + "homepage": "http://www.phpdoc.org", + "keywords": [ + "FQSEN", + "phpDocumentor", + "phpdoc", + "reflection", + "static analysis" + ], + "time": "2015-12-27T11:43:31+00:00" + }, + { + "name": "phpdocumentor/reflection-docblock", + "version": "3.2.2", + "source": { + "type": "git", + "url": "https://github.com/phpDocumentor/ReflectionDocBlock.git", + "reference": "4aada1f93c72c35e22fb1383b47fee43b8f1d157" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/phpDocumentor/ReflectionDocBlock/zipball/4aada1f93c72c35e22fb1383b47fee43b8f1d157", + "reference": "4aada1f93c72c35e22fb1383b47fee43b8f1d157", + "shasum": "" + }, + "require": { + "php": ">=5.5", + "phpdocumentor/reflection-common": "^1.0@dev", + "phpdocumentor/type-resolver": "^0.3.0", + "webmozart/assert": "^1.0" + }, + "require-dev": { + "mockery/mockery": "^0.9.4", + "phpunit/phpunit": "^4.4" + }, + "type": "library", + "autoload": { + "psr-4": { + "phpDocumentor\\Reflection\\": [ + "src/" + ] + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Mike van Riel", + "email": "me@mikevanriel.com" + } + ], + "description": "With this component, a library can provide support for annotations via DocBlocks or otherwise retrieve information that is embedded in a DocBlock.", + "time": "2017-08-08T06:39:58+00:00" + }, + { + "name": "phpdocumentor/type-resolver", + "version": "0.3.0", + "source": { + "type": "git", + "url": "https://github.com/phpDocumentor/TypeResolver.git", + "reference": "fb3933512008d8162b3cdf9e18dba9309b7c3773" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/phpDocumentor/TypeResolver/zipball/fb3933512008d8162b3cdf9e18dba9309b7c3773", + "reference": "fb3933512008d8162b3cdf9e18dba9309b7c3773", + "shasum": "" + }, + "require": { + "php": "^5.5 || ^7.0", + "phpdocumentor/reflection-common": "^1.0" + }, + "require-dev": { + "mockery/mockery": "^0.9.4", + "phpunit/phpunit": "^5.2||^4.8.24" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "phpDocumentor\\Reflection\\": [ + "src/" + ] + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Mike van Riel", + "email": "me@mikevanriel.com" + } + ], + "time": "2017-06-03T08:32:36+00:00" + }, + { + "name": "phpspec/prophecy", + "version": "v1.7.0", + "source": { + "type": "git", + "url": "https://github.com/phpspec/prophecy.git", + "reference": "93d39f1f7f9326d746203c7c056f300f7f126073" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/phpspec/prophecy/zipball/93d39f1f7f9326d746203c7c056f300f7f126073", + "reference": "93d39f1f7f9326d746203c7c056f300f7f126073", + "shasum": "" + }, + "require": { + "doctrine/instantiator": "^1.0.2", + "php": "^5.3|^7.0", + "phpdocumentor/reflection-docblock": "^2.0|^3.0.2", + "sebastian/comparator": "^1.1|^2.0", + "sebastian/recursion-context": "^1.0|^2.0|^3.0" + }, + "require-dev": { + "phpspec/phpspec": "^2.5|^3.2", + "phpunit/phpunit": "^4.8 || ^5.6.5" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.6.x-dev" + } + }, + "autoload": { + "psr-0": { + "Prophecy\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Konstantin Kudryashov", + "email": "ever.zet@gmail.com", + "homepage": "http://everzet.com" + }, + { + "name": "Marcello Duarte", + "email": "marcello.duarte@gmail.com" + } + ], + "description": "Highly opinionated mocking framework for PHP 5.3+", + "homepage": "https://github.com/phpspec/prophecy", + "keywords": [ + "Double", + "Dummy", + "fake", + "mock", + "spy", + "stub" + ], + "time": "2017-03-02T20:05:34+00:00" + }, + { + "name": "phpunit/php-code-coverage", + "version": "4.0.8", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/php-code-coverage.git", + "reference": "ef7b2f56815df854e66ceaee8ebe9393ae36a40d" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/ef7b2f56815df854e66ceaee8ebe9393ae36a40d", + "reference": "ef7b2f56815df854e66ceaee8ebe9393ae36a40d", + "shasum": "" + }, + "require": { + "ext-dom": "*", + "ext-xmlwriter": "*", + "php": "^5.6 || ^7.0", + "phpunit/php-file-iterator": "^1.3", + "phpunit/php-text-template": "^1.2", + "phpunit/php-token-stream": "^1.4.2 || ^2.0", + "sebastian/code-unit-reverse-lookup": "^1.0", + "sebastian/environment": "^1.3.2 || ^2.0", + "sebastian/version": "^1.0 || ^2.0" + }, + "require-dev": { + "ext-xdebug": "^2.1.4", + "phpunit/phpunit": "^5.7" + }, + "suggest": { + "ext-xdebug": "^2.5.1" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "4.0.x-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sb@sebastian-bergmann.de", + "role": "lead" + } + ], + "description": "Library that provides collection, processing, and rendering functionality for PHP code coverage information.", + "homepage": "https://github.com/sebastianbergmann/php-code-coverage", + "keywords": [ + "coverage", + "testing", + "xunit" + ], + "time": "2017-04-02T07:44:40+00:00" + }, + { + "name": "phpunit/php-file-iterator", + "version": "1.4.2", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/php-file-iterator.git", + "reference": "3cc8f69b3028d0f96a9078e6295d86e9bf019be5" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/php-file-iterator/zipball/3cc8f69b3028d0f96a9078e6295d86e9bf019be5", + "reference": "3cc8f69b3028d0f96a9078e6295d86e9bf019be5", + "shasum": "" + }, + "require": { + "php": ">=5.3.3" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.4.x-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sb@sebastian-bergmann.de", + "role": "lead" + } + ], + "description": "FilterIterator implementation that filters files based on a list of suffixes.", + "homepage": "https://github.com/sebastianbergmann/php-file-iterator/", + "keywords": [ + "filesystem", + "iterator" + ], + "time": "2016-10-03T07:40:28+00:00" + }, + { + "name": "phpunit/php-text-template", + "version": "1.2.1", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/php-text-template.git", + "reference": "31f8b717e51d9a2afca6c9f046f5d69fc27c8686" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/php-text-template/zipball/31f8b717e51d9a2afca6c9f046f5d69fc27c8686", + "reference": "31f8b717e51d9a2afca6c9f046f5d69fc27c8686", + "shasum": "" + }, + "require": { + "php": ">=5.3.3" + }, + "type": "library", + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "Simple template engine.", + "homepage": "https://github.com/sebastianbergmann/php-text-template/", + "keywords": [ + "template" + ], + "time": "2015-06-21T13:50:34+00:00" + }, + { + "name": "phpunit/php-timer", + "version": "1.0.9", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/php-timer.git", + "reference": "3dcf38ca72b158baf0bc245e9184d3fdffa9c46f" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/php-timer/zipball/3dcf38ca72b158baf0bc245e9184d3fdffa9c46f", + "reference": "3dcf38ca72b158baf0bc245e9184d3fdffa9c46f", + "shasum": "" + }, + "require": { + "php": "^5.3.3 || ^7.0" + }, + "require-dev": { + "phpunit/phpunit": "^4.8.35 || ^5.7 || ^6.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sb@sebastian-bergmann.de", + "role": "lead" + } + ], + "description": "Utility class for timing", + "homepage": "https://github.com/sebastianbergmann/php-timer/", + "keywords": [ + "timer" + ], + "time": "2017-02-26T11:10:40+00:00" + }, + { + "name": "phpunit/php-token-stream", + "version": "1.4.11", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/php-token-stream.git", + "reference": "e03f8f67534427a787e21a385a67ec3ca6978ea7" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/php-token-stream/zipball/e03f8f67534427a787e21a385a67ec3ca6978ea7", + "reference": "e03f8f67534427a787e21a385a67ec3ca6978ea7", + "shasum": "" + }, + "require": { + "ext-tokenizer": "*", + "php": ">=5.3.3" + }, + "require-dev": { + "phpunit/phpunit": "~4.2" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.4-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + } + ], + "description": "Wrapper around PHP's tokenizer extension.", + "homepage": "https://github.com/sebastianbergmann/php-token-stream/", + "keywords": [ + "tokenizer" + ], + "time": "2017-02-27T10:12:30+00:00" + }, + { + "name": "phpunit/phpunit", + "version": "5.7.21", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/phpunit.git", + "reference": "3b91adfb64264ddec5a2dee9851f354aa66327db" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/3b91adfb64264ddec5a2dee9851f354aa66327db", + "reference": "3b91adfb64264ddec5a2dee9851f354aa66327db", + "shasum": "" + }, + "require": { + "ext-dom": "*", + "ext-json": "*", + "ext-libxml": "*", + "ext-mbstring": "*", + "ext-xml": "*", + "myclabs/deep-copy": "~1.3", + "php": "^5.6 || ^7.0", + "phpspec/prophecy": "^1.6.2", + "phpunit/php-code-coverage": "^4.0.4", + "phpunit/php-file-iterator": "~1.4", + "phpunit/php-text-template": "~1.2", + "phpunit/php-timer": "^1.0.6", + "phpunit/phpunit-mock-objects": "^3.2", + "sebastian/comparator": "^1.2.4", + "sebastian/diff": "^1.4.3", + "sebastian/environment": "^1.3.4 || ^2.0", + "sebastian/exporter": "~2.0", + "sebastian/global-state": "^1.1", + "sebastian/object-enumerator": "~2.0", + "sebastian/resource-operations": "~1.0", + "sebastian/version": "~1.0.3|~2.0", + "symfony/yaml": "~2.1|~3.0" + }, + "conflict": { + "phpdocumentor/reflection-docblock": "3.0.2" + }, + "require-dev": { + "ext-pdo": "*" + }, + "suggest": { + "ext-xdebug": "*", + "phpunit/php-invoker": "~1.1" + }, + "bin": [ + "phpunit" + ], + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "5.7.x-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "The PHP Unit Testing framework.", + "homepage": "https://phpunit.de/", + "keywords": [ + "phpunit", + "testing", + "xunit" + ], + "time": "2017-06-21T08:11:54+00:00" + }, + { + "name": "phpunit/phpunit-mock-objects", + "version": "3.4.4", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/phpunit-mock-objects.git", + "reference": "a23b761686d50a560cc56233b9ecf49597cc9118" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/phpunit-mock-objects/zipball/a23b761686d50a560cc56233b9ecf49597cc9118", + "reference": "a23b761686d50a560cc56233b9ecf49597cc9118", + "shasum": "" + }, + "require": { + "doctrine/instantiator": "^1.0.2", + "php": "^5.6 || ^7.0", + "phpunit/php-text-template": "^1.2", + "sebastian/exporter": "^1.2 || ^2.0" + }, + "conflict": { + "phpunit/phpunit": "<5.4.0" + }, + "require-dev": { + "phpunit/phpunit": "^5.4" + }, + "suggest": { + "ext-soap": "*" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.2.x-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sb@sebastian-bergmann.de", + "role": "lead" + } + ], + "description": "Mock Object library for PHPUnit", + "homepage": "https://github.com/sebastianbergmann/phpunit-mock-objects/", + "keywords": [ + "mock", + "xunit" + ], + "time": "2017-06-30T09:13:00+00:00" + }, + { + "name": "psr/http-message", + "version": "1.0.1", + "source": { + "type": "git", + "url": "https://github.com/php-fig/http-message.git", + "reference": "f6561bf28d520154e4b0ec72be95418abe6d9363" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/http-message/zipball/f6561bf28d520154e4b0ec72be95418abe6d9363", + "reference": "f6561bf28d520154e4b0ec72be95418abe6d9363", + "shasum": "" + }, + "require": { + "php": ">=5.3.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "Psr\\Http\\Message\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "http://www.php-fig.org/" + } + ], + "description": "Common interface for HTTP messages", + "homepage": "https://github.com/php-fig/http-message", + "keywords": [ + "http", + "http-message", + "psr", + "psr-7", + "request", + "response" + ], + "time": "2016-08-06T14:39:51+00:00" + }, + { + "name": "sebastian/code-unit-reverse-lookup", + "version": "1.0.1", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/code-unit-reverse-lookup.git", + "reference": "4419fcdb5eabb9caa61a27c7a1db532a6b55dd18" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/code-unit-reverse-lookup/zipball/4419fcdb5eabb9caa61a27c7a1db532a6b55dd18", + "reference": "4419fcdb5eabb9caa61a27c7a1db532a6b55dd18", + "shasum": "" + }, + "require": { + "php": "^5.6 || ^7.0" + }, + "require-dev": { + "phpunit/phpunit": "^5.7 || ^6.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + } + ], + "description": "Looks up which function or method a line of code belongs to", + "homepage": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/", + "time": "2017-03-04T06:30:41+00:00" + }, + { + "name": "sebastian/comparator", + "version": "1.2.4", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/comparator.git", + "reference": "2b7424b55f5047b47ac6e5ccb20b2aea4011d9be" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/2b7424b55f5047b47ac6e5ccb20b2aea4011d9be", + "reference": "2b7424b55f5047b47ac6e5ccb20b2aea4011d9be", + "shasum": "" + }, + "require": { + "php": ">=5.3.3", + "sebastian/diff": "~1.2", + "sebastian/exporter": "~1.2 || ~2.0" + }, + "require-dev": { + "phpunit/phpunit": "~4.4" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.2.x-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Jeff Welch", + "email": "whatthejeff@gmail.com" + }, + { + "name": "Volker Dusch", + "email": "github@wallbash.com" + }, + { + "name": "Bernhard Schussek", + "email": "bschussek@2bepublished.at" + }, + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + } + ], + "description": "Provides the functionality to compare PHP values for equality", + "homepage": "http://www.github.com/sebastianbergmann/comparator", + "keywords": [ + "comparator", + "compare", + "equality" + ], + "time": "2017-01-29T09:50:25+00:00" + }, + { + "name": "sebastian/diff", + "version": "1.4.3", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/diff.git", + "reference": "7f066a26a962dbe58ddea9f72a4e82874a3975a4" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/diff/zipball/7f066a26a962dbe58ddea9f72a4e82874a3975a4", + "reference": "7f066a26a962dbe58ddea9f72a4e82874a3975a4", + "shasum": "" + }, + "require": { + "php": "^5.3.3 || ^7.0" + }, + "require-dev": { + "phpunit/phpunit": "^4.8.35 || ^5.7 || ^6.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.4-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Kore Nordmann", + "email": "mail@kore-nordmann.de" + }, + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + } + ], + "description": "Diff implementation", + "homepage": "https://github.com/sebastianbergmann/diff", + "keywords": [ + "diff" + ], + "time": "2017-05-22T07:24:03+00:00" + }, + { + "name": "sebastian/environment", + "version": "2.0.0", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/environment.git", + "reference": "5795ffe5dc5b02460c3e34222fee8cbe245d8fac" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/environment/zipball/5795ffe5dc5b02460c3e34222fee8cbe245d8fac", + "reference": "5795ffe5dc5b02460c3e34222fee8cbe245d8fac", + "shasum": "" + }, + "require": { + "php": "^5.6 || ^7.0" + }, + "require-dev": { + "phpunit/phpunit": "^5.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.0.x-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + } + ], + "description": "Provides functionality to handle HHVM/PHP environments", + "homepage": "http://www.github.com/sebastianbergmann/environment", + "keywords": [ + "Xdebug", + "environment", + "hhvm" + ], + "time": "2016-11-26T07:53:53+00:00" + }, + { + "name": "sebastian/exporter", + "version": "2.0.0", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/exporter.git", + "reference": "ce474bdd1a34744d7ac5d6aad3a46d48d9bac4c4" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/ce474bdd1a34744d7ac5d6aad3a46d48d9bac4c4", + "reference": "ce474bdd1a34744d7ac5d6aad3a46d48d9bac4c4", + "shasum": "" + }, + "require": { + "php": ">=5.3.3", + "sebastian/recursion-context": "~2.0" + }, + "require-dev": { + "ext-mbstring": "*", + "phpunit/phpunit": "~4.4" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.0.x-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Jeff Welch", + "email": "whatthejeff@gmail.com" + }, + { + "name": "Volker Dusch", + "email": "github@wallbash.com" + }, + { + "name": "Bernhard Schussek", + "email": "bschussek@2bepublished.at" + }, + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + }, + { + "name": "Adam Harvey", + "email": "aharvey@php.net" + } + ], + "description": "Provides the functionality to export PHP variables for visualization", + "homepage": "http://www.github.com/sebastianbergmann/exporter", + "keywords": [ + "export", + "exporter" + ], + "time": "2016-11-19T08:54:04+00:00" + }, + { + "name": "sebastian/global-state", + "version": "1.1.1", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/global-state.git", + "reference": "bc37d50fea7d017d3d340f230811c9f1d7280af4" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/global-state/zipball/bc37d50fea7d017d3d340f230811c9f1d7280af4", + "reference": "bc37d50fea7d017d3d340f230811c9f1d7280af4", + "shasum": "" + }, + "require": { + "php": ">=5.3.3" + }, + "require-dev": { + "phpunit/phpunit": "~4.2" + }, + "suggest": { + "ext-uopz": "*" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + } + ], + "description": "Snapshotting of global state", + "homepage": "http://www.github.com/sebastianbergmann/global-state", + "keywords": [ + "global state" + ], + "time": "2015-10-12T03:26:01+00:00" + }, + { + "name": "sebastian/object-enumerator", + "version": "2.0.1", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/object-enumerator.git", + "reference": "1311872ac850040a79c3c058bea3e22d0f09cbb7" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/object-enumerator/zipball/1311872ac850040a79c3c058bea3e22d0f09cbb7", + "reference": "1311872ac850040a79c3c058bea3e22d0f09cbb7", + "shasum": "" + }, + "require": { + "php": ">=5.6", + "sebastian/recursion-context": "~2.0" + }, + "require-dev": { + "phpunit/phpunit": "~5" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.0.x-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + } + ], + "description": "Traverses array structures and object graphs to enumerate all referenced objects", + "homepage": "https://github.com/sebastianbergmann/object-enumerator/", + "time": "2017-02-18T15:18:39+00:00" + }, + { + "name": "sebastian/recursion-context", + "version": "2.0.0", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/recursion-context.git", + "reference": "2c3ba150cbec723aa057506e73a8d33bdb286c9a" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/recursion-context/zipball/2c3ba150cbec723aa057506e73a8d33bdb286c9a", + "reference": "2c3ba150cbec723aa057506e73a8d33bdb286c9a", + "shasum": "" + }, + "require": { + "php": ">=5.3.3" + }, + "require-dev": { + "phpunit/phpunit": "~4.4" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.0.x-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Jeff Welch", + "email": "whatthejeff@gmail.com" + }, + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + }, + { + "name": "Adam Harvey", + "email": "aharvey@php.net" + } + ], + "description": "Provides functionality to recursively process PHP variables", + "homepage": "http://www.github.com/sebastianbergmann/recursion-context", + "time": "2016-11-19T07:33:16+00:00" + }, + { + "name": "sebastian/resource-operations", + "version": "1.0.0", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/resource-operations.git", + "reference": "ce990bb21759f94aeafd30209e8cfcdfa8bc3f52" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/resource-operations/zipball/ce990bb21759f94aeafd30209e8cfcdfa8bc3f52", + "reference": "ce990bb21759f94aeafd30209e8cfcdfa8bc3f52", + "shasum": "" + }, + "require": { + "php": ">=5.6.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + } + ], + "description": "Provides a list of PHP built-in functions that operate on resources", + "homepage": "https://www.github.com/sebastianbergmann/resource-operations", + "time": "2015-07-28T20:34:47+00:00" + }, + { + "name": "sebastian/version", + "version": "2.0.1", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/version.git", + "reference": "99732be0ddb3361e16ad77b68ba41efc8e979019" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/version/zipball/99732be0ddb3361e16ad77b68ba41efc8e979019", + "reference": "99732be0ddb3361e16ad77b68ba41efc8e979019", + "shasum": "" + }, + "require": { + "php": ">=5.6" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.0.x-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "Library that helps with managing the version number of Git-hosted PHP projects", + "homepage": "https://github.com/sebastianbergmann/version", + "time": "2016-10-03T07:35:21+00:00" + }, + { + "name": "symfony/yaml", + "version": "v3.3.6", + "source": { + "type": "git", + "url": "https://github.com/symfony/yaml.git", + "reference": "ddc23324e6cfe066f3dd34a37ff494fa80b617ed" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/yaml/zipball/ddc23324e6cfe066f3dd34a37ff494fa80b617ed", + "reference": "ddc23324e6cfe066f3dd34a37ff494fa80b617ed", + "shasum": "" + }, + "require": { + "php": ">=5.5.9" + }, + "require-dev": { + "symfony/console": "~2.8|~3.0" + }, + "suggest": { + "symfony/console": "For validating YAML files using the lint command" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.3-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Component\\Yaml\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony Yaml Component", + "homepage": "https://symfony.com", + "time": "2017-07-23T12:43:26+00:00" + }, + { + "name": "vlucas/phpdotenv", + "version": "v2.4.0", + "source": { + "type": "git", + "url": "https://github.com/vlucas/phpdotenv.git", + "reference": "3cc116adbe4b11be5ec557bf1d24dc5e3a21d18c" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/vlucas/phpdotenv/zipball/3cc116adbe4b11be5ec557bf1d24dc5e3a21d18c", + "reference": "3cc116adbe4b11be5ec557bf1d24dc5e3a21d18c", + "shasum": "" + }, + "require": { + "php": ">=5.3.9" + }, + "require-dev": { + "phpunit/phpunit": "^4.8 || ^5.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.4-dev" + } + }, + "autoload": { + "psr-4": { + "Dotenv\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause-Attribution" + ], + "authors": [ + { + "name": "Vance Lucas", + "email": "vance@vancelucas.com", + "homepage": "http://www.vancelucas.com" + } + ], + "description": "Loads environment variables from `.env` to `getenv()`, `$_ENV` and `$_SERVER` automagically.", + "keywords": [ + "dotenv", + "env", + "environment" + ], + "time": "2016-09-01T10:05:43+00:00" + }, + { + "name": "webmozart/assert", + "version": "1.2.0", + "source": { + "type": "git", + "url": "https://github.com/webmozart/assert.git", + "reference": "2db61e59ff05fe5126d152bd0655c9ea113e550f" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/webmozart/assert/zipball/2db61e59ff05fe5126d152bd0655c9ea113e550f", + "reference": "2db61e59ff05fe5126d152bd0655c9ea113e550f", + "shasum": "" + }, + "require": { + "php": "^5.3.3 || ^7.0" + }, + "require-dev": { + "phpunit/phpunit": "^4.6", + "sebastian/version": "^1.0.1" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.3-dev" + } + }, + "autoload": { + "psr-4": { + "Webmozart\\Assert\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Bernhard Schussek", + "email": "bschussek@gmail.com" + } + ], + "description": "Assertions to validate method input/output with nice error messages.", + "keywords": [ + "assert", + "check", + "validate" + ], + "time": "2016-11-23T20:04:58+00:00" + } + ], + "packages-dev": [ + { + "name": "phpunit/dbunit", + "version": "2.0.3", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/dbunit.git", + "reference": "5c35d74549c21ba55d0ea74ba89d191a51f8cf25" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/dbunit/zipball/5c35d74549c21ba55d0ea74ba89d191a51f8cf25", + "reference": "5c35d74549c21ba55d0ea74ba89d191a51f8cf25", + "shasum": "" + }, + "require": { + "ext-pdo": "*", + "ext-simplexml": "*", + "php": "^5.4 || ^7.0", + "phpunit/phpunit": "^4.0 || ^5.0 || ^6.0", + "symfony/yaml": "^2.1 || ^3.0" + }, + "bin": [ + "dbunit" + ], + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.0.x-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sb@sebastian-bergmann.de", + "role": "lead" + } + ], + "description": "DbUnit port for PHP/PHPUnit to support database interaction testing.", + "homepage": "https://github.com/sebastianbergmann/dbunit/", + "keywords": [ + "database", + "testing", + "xunit" + ], + "time": "2016-12-02T14:39:14+00:00" + } + ], + "aliases": [], + "minimum-stability": "stable", + "stability-flags": [], + "prefer-stable": false, + "prefer-lowest": false, + "platform": [], + "platform-dev": [] +}