.dev/tests/functional/model/class_model_sakila_test.Test.php

Summary

Maintainability
D
3 days
Test Coverage
<?php

require_once dirname(__DIR__) . '/db_real_abstract.php';

/**
 * @requires extension mysqli
 */
class class_model_sakila_test extends db_real_abstract
{
    public static function db_name()
    {
        return self::$DB_NAME;
    }
    public static function table_name($name)
    {
        return $name;
    }
    public static function setUpBeforeClass() : void
    {
        self::$_bak['DB_DRIVER'] = self::$DB_DRIVER;
        self::$DB_DRIVER = 'mysqli';
        self::_connect();
        self::utils()->truncate_database(self::db_name());
        self::$_bak['ERROR_AUTO_REPAIR'] = self::db()->ERROR_AUTO_REPAIR;
        self::db()->ERROR_AUTO_REPAIR = true;
        $GLOBALS['db'] = self::db();

        // unit_tests == name of the custom storage used here
        // Ensure unit_tests will be on top of the storages list
        main()->_custom_class_storages['*_model'] = ['unit_tests' => [__DIR__ . '/fixtures/']] + (array) main()->_custom_class_storages['*_model'];
    }
    public static function tearDownAfterClass() : void
    {
        self::utils()->truncate_database(self::db_name());
        self::$DB_DRIVER = self::$_bak['DB_DRIVER'];
        self::db()->ERROR_AUTO_REPAIR = self::$_bak['ERROR_AUTO_REPAIR'];
    }

    /***/
    public function _fix_sql_php($sql_php)
    {
        $innodb_has_fulltext = self::_innodb_has_fulltext();
        if ( ! $innodb_has_fulltext) {
            // Remove fulltext indexes from db structure before creating table
            foreach ((array) $sql_php['indexes'] as $iname => $idx) {
                if ($idx['type'] == 'fulltext') {
                    unset($sql_php['indexes'][$iname]);
                }
            }
        }
        foreach ((array) $sql_php['fields'] as $fname => $f) {
            unset($sql_php['fields'][$fname]['raw']);
            unset($sql_php['fields'][$fname]['collate']);
            unset($sql_php['fields'][$fname]['charset']);
            if ($f['default'] === 'NULL') {
                $sql_php['fields'][$fname]['default'] = null;
            }
        }
        foreach ((array) $sql_php['indexes'] as $fname => $f) {
            unset($sql_php['indexes'][$fname]['raw']);
        }
        foreach ((array) $sql_php['foreign_keys'] as $fname => $fk) {
            unset($sql_php['foreign_keys'][$fname]['raw']);
            if ($fk['on_update'] === null) {
                $sql_php['foreign_keys'][$fname]['on_update'] = 'RESTRICT';
            }
            if ($fk['on_delete'] === null) {
                $sql_php['foreign_keys'][$fname]['on_delete'] = 'RESTRICT';
            }
        }
        return $sql_php;
    }

    /***/
    public function test_load_fixtures()
    {
        if ($this->_need_skip_test(__FUNCTION__)) {
            return;
        }
        self::utils()->truncate_database(self::db_name());

        $db_prefix = self::db()->DB_PREFIX;
        $plen = strlen($db_prefix);
        $innodb_has_fulltext = self::_innodb_has_fulltext();

        $this->assertEquals([], self::utils()->list_tables(self::db_name()));

        $parser = _class('db_ddl_parser_mysql', 'classes/db/');
        $parser->RAW_IN_RESULTS = false;

        $tables_php = [];
        $ext = '.sql_php.php';
        $globs_php = [
            'fixtures' => __DIR__ . '/fixtures/*' . $ext,
        ];
        foreach ($globs_php as $glob) {
            foreach (glob($glob) as $f) {
                $t_name = substr(basename($f), 0, -strlen($ext));
                $tables_php[$t_name] = include $f; // $data should be loaded from file
            }
        }
        $tables_data = [];
        $ext = '.data.php';
        $globs_data = [
            'fixtures' => __DIR__ . '/fixtures/*' . $ext,
        ];
        foreach ($globs_data as $glob) {
            foreach (glob($glob) as $f) {
                $t_name = substr(basename($f), 0, -strlen($ext));
                $tables_data[$t_name] = include $f; // $data should be loaded from file
            }
        }
        $this->assertNotEmpty($tables_php);
        $this->assertTrue((bool) self::db()->query('SET foreign_key_checks = 0;'));
        foreach ((array) $tables_php as $name => $sql_php) {
            $sql_php = $this->_fix_sql_php($sql_php);
            $this->assertTrue(is_array($sql_php) && count((array) $sql_php) && $sql_php);
            $this->assertTrue((bool) self::utils()->create_table($name, $sql_php), 'creating table: ' . $db_prefix . $name);
            $this->assertTrue((bool) self::utils()->table_exists(self::table_name($db_prefix . $name)));

            $columns = self::utils()->list_columns(self::table_name($db_prefix . $name));
            foreach ((array) $columns as $fname => $f) {
                unset($columns[$fname]['type_raw']);
                unset($columns[$fname]['collate']);
                unset($columns[$fname]['charset']);
            }
            $this->assertEquals($sql_php['fields'], $columns, 'Compare columns with expected sql_php for table: ' . $name);
            $indexes = self::utils()->list_indexes(self::table_name($db_prefix . $name));
            $this->assertEquals($sql_php['indexes'], $indexes, 'Compare indexes with expected sql_php for table: ' . $name);
            $fks = self::utils()->list_foreign_keys(self::table_name($db_prefix . $name));
            if ($plen) {
                foreach ((array) $fks as $fname => $finfo) {
                    $fks[$fname]['ref_table'] = substr($finfo['ref_table'], $plen);
                }
            }
            $this->assertEquals($sql_php['foreign_keys'], $fks, 'Compare indexes with expected sql_php for table: ' . $name);

            $table_data = $tables_data[$name];
            if ($table_data) {
                $this->assertTrue((bool) self::db()->insert_safe($name, $table_data));
            }
            $real_data = self::db()->from($name)->get_all();
            $this->assertEquals($table_data, $real_data);
            if ($i++ > 3) {
                break;
            }
            break;
        }

        $this->assertTrue((bool) self::db()->query('SET foreign_key_checks = 1;'));
    }

    /**
     * @depends test_load_fixtures
     */
    public function test_sakila_basic()
    {
        if ($this->_need_skip_test(__FUNCTION__)) {
            return;
        }

        $actors_data = include __DIR__ . '/fixtures/actor.data.php';
        $actors_data_objects = [];
        foreach ($actors_data as $arr) {
            $actors_data_objects[] = (object) $arr;
        }

        $all_actors = model('actor')->all();
        $this->assertTrue( is_array($all_actors) );
        $this->assertTrue( (count((array)$all_actors) > 0) );
        // $this->assertEquals( $actors_data_objects, $all_actors );
        // $this->assertEquals( $actors_data, $all_actors );

        $raw_first_id = $actors_data[0]['actor_id'];
        $this->assertNotEmpty($raw_first_id);
        $first_actor = model('actor')->find($raw_first_id);
        $this->assertNotEmpty($actors_data_objects[0]);

        foreach ($actors_data_objects[0] as $k => $v) {
            $this->assertEquals($v, $first_actor->$k);
        }

        $same = true;
        foreach ($actors_data_objects[0] as $k => $v) {
            if ($v != $first_actor->$k) {
                $same = false;
                break;
            }
        }
        $this->assertTrue( $same, 'These objects should be same: '. print_r($actors_data_objects[0], 1). PHP_EOL. print_r($first_actor, 1) );
        // $this->assertEquals( $actors_data_objects[0], $first_actor );
        $this->assertEquals($raw_first_id, $first_actor->actor_id);

        $raw_second_id = $actors_data[1]['actor_id'];
        $this->assertNotEmpty($raw_second_id);

        $second_actor = model('actor')->find($raw_second_id);
        $this->assertNotEmpty( $actors_data_objects[1] );
        // $this->assertEquals( $actors_data_objects[1], $second_actor );
        $this->assertEquals( $raw_second_id, $second_actor->actor_id );

        $raw_some_actors = array();
        foreach ($actors_data_objects as $i => $a) {
            if ($a->actor_id < 10) {
                $raw_some_actors[$i] = $a;
            }
        }
        $this->assertNotEmpty( $raw_some_actors );

        // $some_actors = model('actor')->all('actor_id < 10');
        // $this->assertEquals( $raw_some_actors, $some_actors );
        // unset($some_actors);

        // $some_actors = model('actor')->where('actor_id < 10')->all();
        // $this->assertEquals( $raw_some_actors, $some_actors );
        // unset($some_actors);

        // $some_actors = model('actor')->where('actor_id < 10')->limit(1)->all();
        // $this->assertEquals( array_slice($raw_some_actors, 0, 1, true), $some_actors );
        // unset($some_actors);

        // $some_actors = model('actor')->where('actor_id < 10')->limit(1,1)->all();
        // $this->assertEquals( current(array_slice($raw_some_actors, 1, 1, true)), current($some_actors) );
        // $this->assertNotNull( $some_actors[0]->first_name );
        // unset($some_actors);

        // $some_actors = model('actor')->where('actor_id < 10')->select('actor_id')->limit(0,1)->all();
        // $this->assertEquals( $raw_some_actors[0]->actor_id, $some_actors[0]->actor_id );
        // $this->assertNull( $some_actors[0]->first_name );
        // unset($some_actors);

        // $some_actors = model('actor')->all(1);
        // $this->assertEquals( $raw_some_actors[0], $some_actors[0] );
        // unset($some_actors);

        // $some_actors = model('actor')->get(1);
        // $this->assertEquals( $raw_some_actors[0], $some_actors );
        // unset($some_actors);

        // $some_actors = model('actor')->whereid(1)->all();
        // $this->assertEquals( $raw_some_actors[0], $some_actors[0] );
        // unset($some_actors);

        // $some_actors = model('actor')->whereid(1)->get();
        // $this->assertEquals( $raw_some_actors[0], $some_actors );
        // unset($some_actors);

        // $some_actors = model('actor')->where('actor_id < 10')->order_by('actor_id desc')->all();
        // $this->assertEquals( array_reverse($raw_some_actors), $some_actors );
        // unset($some_actors);

        // $some_actors = model('actor')->all(array('where' => 'actor_id < 10', 'order_by' => 'actor_id desc'));
        // $this->assertEquals( array_reverse($raw_some_actors), $some_actors );
        // unset($some_actors);
    }

    /**
     * @depends test_load_fixtures
     */
    public function test_sakila_save()
    {
        if ($this->_need_skip_test(__FUNCTION__)) {
            return;
        }

        $actors_data = include __DIR__ . '/fixtures/actor.data.php';
        $actors_data_objects = [];
        foreach ($actors_data as $arr) {
            $actors_data_objects[] = (object) $arr;
        }

        $raw_first_id = $actors_data[0]['actor_id'];
        $this->assertNotEmpty($raw_first_id);
        $first_actor = model('actor')->find($raw_first_id);
        $new_name = 'some new name';
        $this->assertNotEmpty($first_actor->first_name);
        $this->assertNotEquals($first_actor->first_name, $new_name);
        $first_actor->first_name = $new_name;
        //        $first_actor->save();
        $this->assertEquals($first_actor->first_name, $new_name);

        $first_actor_copy = model('actor')->find($raw_first_id);
        $this->assertNotEquals($first_actor, $first_actor_copy);
        //        $this->assertEquals( $first_actor_copy->first_name, $new_name );
    }

    /**
     * @depends test_load_fixtures
     */
    public function test_sakila_relations()
    {
        if ($this->_need_skip_test(__FUNCTION__)) {
            return;
        }

        $actors_data = include __DIR__ . '/fixtures/actor.data.php';
        $actors_data_objects = [];
        foreach ($actors_data as $arr) {
            $actors_data_objects[] = (object) $arr;
        }

        // One-one relation test
        //        print_r(
        //            self::utils()->table_info('actor')
        //        );


        //        $all_actors_having_films = model('actor')->has('films')->all();
        //print_r($all_actors_having_films);
        //        $this->assertEquals( array_reverse($raw_some_actors), $some_actors );
        //        unset($some_actors);

        //        $all_film_titles_with_actor1 = foreach (model('actor')->find(1)->films() as $film) { echo $film->title; }
        //        $film1_titles_with_actor1 = model('actor')->find(1)->films()->first()->title;
        //        $film1_titles_with_actor1 = foreach (model('actor')->with('films') as $actor) { echo $actor->films()->first()->title; }
    }

    /**
     * @depends test_load_fixtures
     */
    public function test_sakila_all_models()
    {
        if ($this->_need_skip_test(__FUNCTION__)) {
            return;
        }
        /*
                $model_base = _class('model');
                $this->assertTrue( is_object($model_base) );
                $this->assertTrue( is_a($model_base, 'yf_model') );
                $this->assertSame( $model_base, _class('yf_model') );
        
                $base_methods = get_class_methods($model_base);
        #        $base_vars = get_object_vars($model_base);
        
                $db_prefix = self::db()->DB_PREFIX;
                $plen = strlen($db_prefix);
        
                foreach ((array)self::utils()->list_tables(self::db_name()) as $table) {
                    $table = substr($table, $plen);
                    $model = self::$db->model($table);
                    $methods = get_class_methods($model);
                    $model_specific_methods = array_diff($methods, $base_methods);
        #echo $table.PHP_EOL;
        #print_r($model_specific_methods);
                    foreach ($model_specific_methods as $_method) {
                        if (substr($_method, 0, 1) === '_') {
                            continue;
                        }
        #echo $_method.PHP_EOL;
                        $result = $model->$_method()->get();
        #var_dump($result);
                    }
        #            $vars = get_object_vars($model);
        #print_r(array_diff($vars, $base_vars));
                }
        */
    }

    /**
     * Just for tests development.
     */
    public function test_dump_sakila_data()
    {
        /*
                $db_name = 'sakila';
                foreach((array)self::utils()->list_tables($db_name) as $table) {
                    $file = __DIR__.'/fixtures/'.$table.'.data.php';
                    if (file_exists($file)) {
                        continue;
                    }
                    $data = self::db()->get_all('SELECT * FROM '.$db_name.'.'.$table);
                    if (empty($data)) {
                        continue;
                    }
                    echo 'Saved data ('.count((array)$data).'): '.$file. PHP_EOL;
                    file_put_contents($file, '<?'.'php'.PHP_EOL.'return '._var_export($data, 1).';');
                }
        */
    }
}