From bc604b992e10177470f9692036574110f73fcc7e Mon Sep 17 00:00:00 2001 From: Duncan Sommerville Date: Wed, 28 Jan 2015 13:19:50 -0500 Subject: [PATCH] CC-5986 - Fixed unit tests, removed unnecessary code from service execution files --- airtime_mvc/application/Bootstrap.php | 8 +- airtime_mvc/application/models/StoredFile.php | 6 +- airtime_mvc/tests/application/bootstrap.php | 5 +- .../application/helpers/AirtimeInstall.php | 390 ++++++++++++++++++ .../tests/application/helpers/TestHelper.php | 4 +- airtime_mvc/tests/runtests.sh | 2 +- install | 4 - .../media-monitor/bin/airtime-media-monitor | 12 - .../media-monitor/media_monitor/__main__.py | 11 +- python_apps/pypo/bin/airtime-playout | 12 - python_apps/pypo/pypo/__main__.py | 11 +- 11 files changed, 424 insertions(+), 41 deletions(-) create mode 100644 airtime_mvc/tests/application/helpers/AirtimeInstall.php diff --git a/airtime_mvc/application/Bootstrap.php b/airtime_mvc/application/Bootstrap.php index 96bd14909..5f69c7b3b 100644 --- a/airtime_mvc/application/Bootstrap.php +++ b/airtime_mvc/application/Bootstrap.php @@ -25,7 +25,7 @@ require_once __DIR__.'/forms/helpers/CustomDecorators.php'; require_once __DIR__.'/controllers/plugins/RabbitMqPlugin.php'; require_once __DIR__.'/upgrade/Upgrades.php'; -require_once (APPLICATION_PATH . "logging/Logging.php"); +require_once (APPLICATION_PATH . "/logging/Logging.php"); Logging::setLogPath('/var/log/airtime/zendphp.log'); Config::setAirtimeVersion(); @@ -81,7 +81,11 @@ class Bootstrap extends Zend_Application_Bootstrap_Bootstrap } protected function _initUpgrade() { - UpgradeManager::checkIfUpgradeIsNeeded(); //This will do the upgrade too if it's needed... + /* We need to wrap this here so that we aren't checking when we're running the unit test suite + */ + if (getenv("AIRTIME_UNIT_TEST") != 1) { + UpgradeManager::checkIfUpgradeIsNeeded(); //This will do the upgrade too if it's needed... + } } protected function _initHeadLink() diff --git a/airtime_mvc/application/models/StoredFile.php b/airtime_mvc/application/models/StoredFile.php index 2c97d41d3..2845b7a69 100644 --- a/airtime_mvc/application/models/StoredFile.php +++ b/airtime_mvc/application/models/StoredFile.php @@ -1079,14 +1079,16 @@ SQL; $LIQUIDSOAP_ERRORS = array('TagLib: MPEG::Properties::read() -- Could not find a valid last MPEG frame in the stream.'); // Ask Liquidsoap if file is playable - $ls_command = sprintf('/usr/bin/airtime-liquidsoap -v -c "output.dummy(audio_to_stereo(single(%s)))" 2>&1', + /* CC-5990/5991 - Changed to point directly to liquidsoap, removed PATH export */ + $command = sprintf('liquidsoap -v -c "output.dummy(audio_to_stereo(single(%s)))" 2>&1', escapeshellarg($audio_file)); - $command = "export PATH=/usr/local/bin:/usr/bin:/bin/usr/bin/ && $ls_command"; exec($command, $output, $rv); $isError = count($output) > 0 && in_array($output[0], $LIQUIDSOAP_ERRORS); + Logging::info("Is error?! : " . $isError); + Logging::info("ls playability response: " . $rv); return ($rv == 0 && !$isError); } diff --git a/airtime_mvc/tests/application/bootstrap.php b/airtime_mvc/tests/application/bootstrap.php index 9852bab8e..d8c6abcc3 100644 --- a/airtime_mvc/tests/application/bootstrap.php +++ b/airtime_mvc/tests/application/bootstrap.php @@ -3,7 +3,10 @@ error_reporting(E_ALL | E_STRICT); // Define path to application directory defined('APPLICATION_PATH') - || define('APPLICATION_PATH', realpath(dirname(__FILE__) . '/../../application')); + || define('APPLICATION_PATH', realpath(dirname(__FILE__) . '/../../application/')); + +// Define path to configs directory +define('CONFIG_PATH', APPLICATION_PATH . '/configs/'); // Define application environment defined('APPLICATION_ENV') diff --git a/airtime_mvc/tests/application/helpers/AirtimeInstall.php b/airtime_mvc/tests/application/helpers/AirtimeInstall.php new file mode 100644 index 000000000..3f9936434 --- /dev/null +++ b/airtime_mvc/tests/application/helpers/AirtimeInstall.php @@ -0,0 +1,390 @@ +query($sql)->fetchColumn(0); + } catch (PDOException $e){ + // no pref table therefore Airtime is not installed. + //We only get here if airtime database exists, but the table doesn't + //This state sometimes happens if a previous Airtime uninstall couldn't remove + //the database because it was busy, so it just removed the tables instead. + return null; + } + //if version is empty string, then version is older than version 1.8.0 + if ($version == '') { + try { + // If this table exists, then it's version 1.7.0 + $sql = "SELECT * FROM cc_show_rebroadcast LIMIT 1"; + $result = $con->query($sql)->fetchColumn(0); + $version = "1.7.0"; + } catch (Exception $e) { + $version = null; + } + } + return $version; + } + public static function DbTableExists($p_name) + { + $con = Propel::getConnection(); + try { + $sql = "SELECT * FROM ".$p_name." LIMIT 1"; + $con->query($sql); + } catch (PDOException $e){ + return false; + } + return true; + } + public static function InstallQuery($sql, $verbose = true) + { + $con = Propel::getConnection(); + try { + $con->exec($sql); + if ($verbose) { + echo "done.\n"; + } + } catch (Exception $e) { + echo "Error!\n".$e->getMessage()."\n"; + echo " SQL statement was:\n"; + echo " ".$sql."\n\n"; + } + } + public static function DropSequence($p_sequenceName) + { + AirtimeInstall::InstallQuery("DROP SEQUENCE IF EXISTS $p_sequenceName", false); + } + + + /** + * Try to connect to the database. Return true on success, false on failure. + * @param boolean $p_exitOnError + * Exit the program on failure. + * @return boolean + */ + public static function DbConnect($p_exitOnError = true) + { + $CC_CONFIG = Config::getConfig(); + try { + $con = Propel::getConnection(); + } catch (Exception $e) { + echo $e->getMessage().PHP_EOL; + echo "Database connection problem.".PHP_EOL; + echo "Check if database '{$CC_CONFIG['dsn']['database']}' exists". + " with corresponding permissions.".PHP_EOL; + if ($p_exitOnError) { + exit(1); + } + return false; + } + return true; + } + /* TODO: This function should be moved to the media-monitor + * install script. */ + public static function InstallStorageDirectory() + { + $CC_CONFIG = Config::getConfig(); + echo "* Storage directory setup".PHP_EOL; + $ini = parse_ini_file(__DIR__."/airtime-install.ini"); + $stor_dir = $ini["storage_dir"]; + $dirs = array($stor_dir, $stor_dir."/organize"); + foreach ($dirs as $dir){ + if (!file_exists($dir)) { + if (mkdir($dir, 02775, true)){ + $rp = realpath($dir); + echo "* Directory $rp created".PHP_EOL; + } else { + echo "* Failed creating {$dir}".PHP_EOL; + exit(1); + } + } + else if (is_writable($dir)) { + $rp = realpath($dir); + echo "* Skipping directory already exists: $rp".PHP_EOL; + } + else { + $rp = realpath($dir); + echo "* Error: Directory already exists, but is not writable: $rp".PHP_EOL; + exit(1); + } + echo "* Giving Apache permission to access $rp".PHP_EOL; + $success = chown($rp, $CC_CONFIG["webServerUser"]); + $success = chgrp($rp, $CC_CONFIG["webServerUser"]); + $success = chmod($rp, 0775); + } + } + public static function CreateDatabaseUser() + { + $CC_CONFIG = Config::getConfig(); + echo " * Creating Airtime database user".PHP_EOL; + $username = $CC_CONFIG['dsn']['username']; + $password = $CC_CONFIG['dsn']['password']; + $command = "echo \"CREATE USER $username ENCRYPTED PASSWORD '$password' LOGIN CREATEDB NOCREATEUSER;\" | su postgres -c psql 2>/dev/null"; + @exec($command, $output, $results); + if ($results == 0) { + echo " * Database user '{$CC_CONFIG['dsn']['username']}' created.".PHP_EOL; + } else { + if (count($output) > 0) { + echo " * Could not create user '{$CC_CONFIG['dsn']['username']}': ".PHP_EOL; + echo implode(PHP_EOL, $output); + } + else { + echo " * Database user '{$CC_CONFIG['dsn']['username']}' already exists.".PHP_EOL; + } + } + } + public static function CreateDatabase() + { + $CC_CONFIG = Config::getConfig(); + $database = $CC_CONFIG['dsn']['database']; + $username = $CC_CONFIG['dsn']['username']; + #$command = "echo \"CREATE DATABASE $database OWNER $username\" | su postgres -c psql 2>/dev/null"; + + echo " * Creating Airtime database: " . $database . PHP_EOL; + + putenv("LC_ALL=en_CA.UTF-8"); //Squash warnings when running unit tests + $command = "su postgres -c \"psql -l | cut -f2 -d' ' | grep -w '{$database}'\";"; + exec($command, $output, $rv); + if ($rv == 0) { + //database already exists + echo "Database already exists." . PHP_EOL; + return true; + } + $command = "sudo -i -u postgres psql postgres -c \"CREATE DATABASE ".$database." WITH ENCODING 'UTF8' TEMPLATE template0 OWNER ".$username."\""; + @exec($command, $output, $results); + if ($results == 0) { + echo " * Database $database created.".PHP_EOL; + } else { + if (count($output) > 0) { + echo " * Could not create database $database: ".PHP_EOL; + echo implode(PHP_EOL, $output); + } + else { + echo " * Database $database already exists.".PHP_EOL; + } + } + $databaseExisted = ($results != 0); + return $databaseExisted; + } + public static function InstallPostgresScriptingLanguage() + { + $con = Propel::getConnection(); + // Install postgres scripting language + $sql = 'SELECT COUNT(*) FROM pg_language WHERE lanname = \'plpgsql\''; + $langIsInstalled = $con->query($sql)->fetchColumn(0); + if ($langIsInstalled == '0') { + echo " * Installing Postgres scripting language".PHP_EOL; + $sql = "CREATE LANGUAGE 'plpgsql'"; + AirtimeInstall::InstallQuery($sql, false); + } else { + echo " * Postgres scripting language already installed".PHP_EOL; + } + } + public static function CreateDatabaseTables($p_dbuser, $p_dbpasswd, $p_dbname, $p_dbhost) + { + echo " * Creating database tables".PHP_EOL; + // Put Propel sql files in Database + //$command = AirtimeInstall::CONF_DIR_WWW."/library/propel/generator/bin/propel-gen ".AirtimeInstall::CONF_DIR_WWW."/build/ insert-sql 2>/dev/null"; + $dir = self::GetAirtimeSrcDir()."/build/sql/"; + $files = array("schema.sql", "sequences.sql", "views.sql", "triggers.sql", "defaultdata.sql"); + foreach ($files as $f){ + $command = "export PGPASSWORD=$p_dbpasswd && psql --username $p_dbuser --dbname $p_dbname --host $p_dbhost --file $dir$f 2>&1"; + @exec($command, $output, $results); + } + AirtimeInstall::$databaseTablesCreated = true; + } + public static function BypassMigrations($dir, $version) + { + $appDir = AirtimeInstall::GetAirtimeSrcDir(); + $command = "php $appDir/library/doctrine/migrations/doctrine-migrations.phar ". + "--configuration=$dir/../../DoctrineMigrations/migrations.xml ". + "--db-configuration=$appDir/library/doctrine/migrations/migrations-db.php ". + "--no-interaction --add migrations:version $version"; + system($command); + } + public static function MigrateTablesToVersion($dir, $version) + { + $appDir = AirtimeInstall::GetAirtimeSrcDir(); + $command = "php $appDir/library/doctrine/migrations/doctrine-migrations.phar ". + "--configuration=$dir/../../DoctrineMigrations/migrations.xml ". + "--db-configuration=$appDir/library/doctrine/migrations/migrations-db.php ". + "--no-interaction migrations:migrate $version"; + system($command); + } + public static function SetAirtimeVersion($p_version) + { + $con = Propel::getConnection(); + $sql = "DELETE FROM cc_pref WHERE keystr = 'system_version'"; + $con->exec($sql); + Application_Model_Preference::SetAirtimeVersion($p_version); + } + public static function SetUniqueId() + { + $uniqueId = md5(uniqid("", true)); + Application_Model_Preference::SetUniqueId($uniqueId); + } + public static function GetAirtimeVersion() + { + $con = Propel::getConnection(); + $sql = "SELECT valstr FROM cc_pref WHERE keystr = 'system_version' LIMIT 1"; + $version = $con->query($sql)->fetchColumn(0); + return $version; + } + public static function DeleteFilesRecursive($p_path) + { + $command = "rm -rf \"$p_path\""; + exec($command); + } + public static function InstallPhpCode() + { + $CC_CONFIG = Config::getConfig(); + echo "* Installing PHP code to ".AirtimeInstall::CONF_DIR_WWW.PHP_EOL; + exec("mkdir -p ".AirtimeInstall::CONF_DIR_WWW); + exec("cp -R ".AirtimeInstall::GetAirtimeSrcDir()."/* ".AirtimeInstall::CONF_DIR_WWW); + } + public static function UninstallPhpCode() + { + echo "* Removing PHP code from ".AirtimeInstall::CONF_DIR_WWW.PHP_EOL; + exec('rm -rf "'.AirtimeInstall::CONF_DIR_WWW.'"'); + } + public static function DirCheck() + { + echo "Legend: \"+\" means the dir/file exists, \"-\" means that it does not.".PHP_EOL; + $dirs = array(AirtimeInstall::CONF_DIR_BINARIES, + AirtimeInstall::CONF_DIR_WWW, + AirtimeIni::CONF_FILE_AIRTIME, + AirtimeIni::CONF_FILE_LIQUIDSOAP, + AirtimeIni::CONF_FILE_PYPO, + AirtimeIni::CONF_FILE_RECORDER, + "/usr/lib/airtime/pypo", + "/var/log/airtime", + "/var/log/airtime/pypo", + "/var/tmp/airtime/pypo"); + foreach ($dirs as $f) { + if (file_exists($f)) { + echo "+ $f".PHP_EOL; + } else { + echo "- $f".PHP_EOL; + } + } + } + public static function CreateZendPhpLogFile(){ + $CC_CONFIG = Config::getConfig(); + $path = AirtimeInstall::CONF_DIR_LOG; + $file = $path.'/zendphp.log'; + if (!file_exists($path)){ + mkdir($path, 0755, true); + } + touch($file); + chmod($file, 0644); + chown($file, $CC_CONFIG['webServerUser']); + chgrp($file, $CC_CONFIG['webServerUser']); + } + public static function RemoveLogDirectories(){ + $path = AirtimeInstall::CONF_DIR_LOG; + echo "* Removing logs directory ".$path.PHP_EOL; + exec("rm -rf \"$path\""); + } + public static function CreateCronFile(){ + echo "* Creating Cron File".PHP_EOL; + // Create CRON task to run every day. Time of day is initialized to a random time. + $hour = rand(0,23); + $minute = rand(0,59); + $fp = fopen('/etc/cron.d/airtime-crons','w'); + fwrite($fp, "$minute $hour * * * root /usr/lib/airtime/utils/phone_home_stat\n"); + fclose($fp); + } + public static function removeVirtualEnvDistributeFile(){ + echo "* Removing distribute-0.6.10.tar.gz".PHP_EOL; + if(file_exists('/usr/share/python-virtualenv/distribute-0.6.10.tar.gz')){ + exec("rm -f /usr/share/python-virtualenv/distribute-0.6.10.tar.gz"); + } + } + public static function printUsage($opts) + { + $msg = $opts->getUsageMessage(); + echo PHP_EOL."Usage: airtime-install [options]"; + echo substr($msg, strpos($msg, "\n")).PHP_EOL; + } + public static function getOpts() + { + try { + $autoloader = Zend_Loader_Autoloader::getInstance(); + $opts = new Zend_Console_Getopt( + array( + 'help|h' => 'Displays usage information.', + 'overwrite|o' => 'Overwrite any existing config files.', + 'preserve|p' => 'Keep any existing config files.', + 'no-db|n' => 'Turn off database install.', + 'reinstall|r' => 'Force a fresh install of this Airtime Version', + 'webonly|w' => 'Install only web files' + ) + ); + $opts->parse(); + } catch (Zend_Console_Getopt_Exception $e) { + print $e->getMessage() .PHP_EOL; + AirtimeInstall::printUsage($opts); + return NULL; + } + return $opts; + } + public static function checkPHPVersion() + { + if (PHP_VERSION_ID < 50300) + { + echo "Error: Airtime requires PHP 5.3 or greater."; + return false; + } + return true; + } +} \ No newline at end of file diff --git a/airtime_mvc/tests/application/helpers/TestHelper.php b/airtime_mvc/tests/application/helpers/TestHelper.php index c33103f8e..950d36c83 100644 --- a/airtime_mvc/tests/application/helpers/TestHelper.php +++ b/airtime_mvc/tests/application/helpers/TestHelper.php @@ -62,7 +62,7 @@ class TestHelper // cc_subjs - Most of Airtime requires an admin account to work, which has id=1, // so don't clear it. // cc_music_dirs - Has foreign key constraints against cc_files, so we clear cc_files - // first and ckear cc_music_dirs after + // first and clear cc_music_dirs after $tablesToNotClear = array("cc_subjs", "cc_music_dirs"); $con->beginTransaction(); @@ -113,7 +113,7 @@ class TestHelper public static function setupZendBootstrap() { - $application = new Zend_Application(APPLICATION_ENV, APPLICATION_PATH .'/configs/application.ini'); + $application = new Zend_Application(APPLICATION_ENV, CONFIG_PATH . 'application.ini'); $application->bootstrap(); return $application; } diff --git a/airtime_mvc/tests/runtests.sh b/airtime_mvc/tests/runtests.sh index faf6628ef..abe2d2ba5 100755 --- a/airtime_mvc/tests/runtests.sh +++ b/airtime_mvc/tests/runtests.sh @@ -33,5 +33,5 @@ DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" cd $DIR #Run the unit tests -phpunit --log-junit test_results.xml +phpunit --verbose --log-junit test_results.xml diff --git a/install b/install index 220d92b5a..7b7054fc2 100755 --- a/install +++ b/install @@ -392,10 +392,6 @@ verbose "\n * Installing pypo..." loudCmd "python ${AIRTIMEROOT}/python_apps/pypo/setup.py install" verbose "...Done" -verbose "\n * Creating liquidsoap symlink..." -ln -sf /usr/bin/liquidsoap /usr/bin/airtime-liquidsoap -verbose "...Done" - for i in /etc/init/airtime*.template; do chmod 644 $i sed -i "s/WEB_USER/${web_user}/g" $i diff --git a/python_apps/media-monitor/bin/airtime-media-monitor b/python_apps/media-monitor/bin/airtime-media-monitor index 25fa771d8..00e729178 100755 --- a/python_apps/media-monitor/bin/airtime-media-monitor +++ b/python_apps/media-monitor/bin/airtime-media-monitor @@ -1,15 +1,3 @@ #!/bin/bash -exec 2>&1 - -set +e -cat /etc/default/locale | grep -i "LANG=.*UTF-\?8" -set -e -if [ "$?" != "0" ]; then - echo "non UTF-8 default locale found in /etc/default/locale." > /var/log/airtime/media-monitor/error.log - exit 1 -fi - -export LC_ALL=`cat /etc/default/locale | grep "LANG=" | cut -d= -f2 | tr -d "\n\""` - exec python -m media_monitor > /var/log/airtime/media-monitor/py-interpreter.log 2>&1 diff --git a/python_apps/media-monitor/media_monitor/__main__.py b/python_apps/media-monitor/media_monitor/__main__.py index e98365cc6..057eef53f 100644 --- a/python_apps/media-monitor/media_monitor/__main__.py +++ b/python_apps/media-monitor/media_monitor/__main__.py @@ -1,11 +1,16 @@ import logging +import locale import time import sys import os import mm2.mm2 as mm2 from std_err_override import LogWriter +locale.setlocale(locale.LC_ALL, '') -global_cfg = '/etc/airtime/airtime.conf' -logging_cfg = os.path.join(os.path.dirname(__file__), 'logging.cfg') +def run(): + global_cfg = '/etc/airtime/airtime.conf' + logging_cfg = os.path.join(os.path.dirname(__file__), 'logging.cfg') + + mm2.main( global_cfg, logging_cfg ) -mm2.main( global_cfg, logging_cfg ) +run() \ No newline at end of file diff --git a/python_apps/pypo/bin/airtime-playout b/python_apps/pypo/bin/airtime-playout index 4cc3d6c35..5187c0ccd 100755 --- a/python_apps/pypo/bin/airtime-playout +++ b/python_apps/pypo/bin/airtime-playout @@ -1,15 +1,3 @@ #!/bin/bash -set +e -cat /etc/default/locale | grep -i "LANG=.*UTF-\?8" > /dev/null -set -e -if [ "$?" != "0" ]; then - echo "non UTF-8 default locale found in /etc/default/locale." > /var/log/airtime/pypo/error.log - exit 1 -fi - -export HOME="/var/tmp/airtime/pypo/" -export LC_ALL=`cat /etc/default/locale | grep "LANG=" | cut -d= -f2 | tr -d "\n\""` -export TERM=xterm - exec python -m pypo > /var/log/airtime/pypo/py-interpreter.log 2>&1 diff --git a/python_apps/pypo/pypo/__main__.py b/python_apps/pypo/pypo/__main__.py index e7dbdaad9..be70a23fe 100644 --- a/python_apps/pypo/pypo/__main__.py +++ b/python_apps/pypo/pypo/__main__.py @@ -76,9 +76,16 @@ parser.add_option("-c", LIQUIDSOAP_MIN_VERSION = "1.1.1" +PYPO_HOME='/var/tmp/airtime/pypo/' -#need to wait for Python 2.7 for this.. -#logging.captureWarnings(True) +def configure_environment(): + os.environ["HOME"] = PYPO_HOME + os.environ["TERM"] = 'xterm' + +configure_environment() + +# need to wait for Python 2.7 for this.. +logging.captureWarnings(True) # configure logging try: