From 80ed9fea8dd5486b1afba9090b82c7f75235517b Mon Sep 17 00:00:00 2001 From: adamgsoc2013 Date: Sat, 29 Jun 2013 22:16:52 +0800 Subject: [PATCH 1/3] 1. add UT for import ODS 2. fix warning in source code when import ODS file --- libraries/plugins/import/ImportOds.class.php | 3 + test/classes/plugin/import/ImportOds_test.php | 185 ++++++++++++++++++ test/test_data/db_test.ods | Bin 0 -> 2576 bytes 3 files changed, 188 insertions(+) create mode 100644 test/classes/plugin/import/ImportOds_test.php create mode 100644 test/test_data/db_test.ods diff --git a/libraries/plugins/import/ImportOds.class.php b/libraries/plugins/import/ImportOds.class.php index 9bf02a2b3b..d0911d779c 100644 --- a/libraries/plugins/import/ImportOds.class.php +++ b/libraries/plugins/import/ImportOds.class.php @@ -161,6 +161,9 @@ class ImportOds extends ImportPlugin * result in increased performance without the need to * alter the code in any way. It's basically a freebee. */ + + //fix import warning: simplexml_load_string(): namespace error : Namespace prefix number is not defined + $buffer = str_replace("number:", "number_", $buffer); $xml = simplexml_load_string($buffer, "SimpleXMLElement", LIBXML_COMPACT); unset($buffer); diff --git a/test/classes/plugin/import/ImportOds_test.php b/test/classes/plugin/import/ImportOds_test.php new file mode 100644 index 0000000000..1ccf46b9db --- /dev/null +++ b/test/classes/plugin/import/ImportOds_test.php @@ -0,0 +1,185 @@ +object = new ImportOds(); + + //setting + $GLOBALS['finished'] = false; + $GLOBALS['read_limit'] = 100000000; + $GLOBALS['offset'] = 0; + $GLOBALS['cfg']['Server']['DisableIS'] = false; + $GLOBALS['cfg']['ServerDefault'] = 0; + $GLOBALS['cfg']['AllowUserDropDatabase'] = false; + $GLOBALS['cfg']['MySQLManualType'] = 'none'; + + $GLOBALS['import_file'] = 'test/test_data/db_test.ods'; + + /** + * Load interface for zip extension. + */ + include_once 'libraries/zip_extension.lib.php'; + $result = PMA_getZipContents($GLOBALS['import_file']); + $GLOBALS['import_text'] = $result["data"]; + $GLOBALS['compression'] = 'application/zip'; + $GLOBALS['read_multiply'] = 10; + $GLOBALS['import_type'] = 'Xml'; + $GLOBALS['import_handle'] = @fopen($GLOBALS['import_file'], 'r'); + + //varible for Ods + $_REQUEST['ods_recognize_percentages'] = true; + $_REQUEST['ods_recognize_currency'] = true; + $_REQUEST['ods_empty_rows'] = true; + } + + /** + * Tears down the fixture, for example, closes a network connection. + * This method is called after a test is executed. + * + * @access protected + * @return void + */ + protected function tearDown() + { + unset($this->object); + } + + /** + * Test for getProperties + * + * @return void + * + * @group medium + */ + public function testGetProperties() + { + $properties = $this->object->getProperties(); + $this->assertEquals( + __('OpenDocument Spreadsheet'), + $properties->getText() + ); + $this->assertEquals( + 'ods', + $properties->getExtension() + ); + $this->assertEquals( + __('Options'), + $properties->getOptionsText() + ); + } + + /** + * Test for doImport + * + * @return void + * + * @group medium + */ + public function testDoImport() + { + //$sql_query_disabled will show the import SQL detail + //$import_notice will show the import detail result + global $import_notice, $sql_query, $sql_query_disabled; + $sql_query_disabled = false; + + //Mock DBI + $dbi = $this->getMockBuilder('PMA_DatabaseInterface') + ->disableOriginalConstructor() + ->getMock(); + $GLOBALS['dbi'] = $dbi; + + //Test function called + $this->object->doImport(); + + //asset that all sql are executed + $this->assertContains( + 'CREATE DATABASE IF NOT EXISTS `ODS_DB` DEFAULT CHARACTER SET utf8 COLLATE utf8_general_ci', + $sql_query + ); + $this->assertContains( + 'CREATE TABLE IF NOT EXISTS `ODS_DB`.`pma_bookmark`', + $sql_query + ); + $this->assertContains( + "INSERT INTO `ODS_DB`.`pma_bookmark` (`A`, `B`, `C`, `D`, `E`) VALUES (1, 'dbbase', '', 'ddd', '')", + $sql_query + ); + + //asset that all databases and tables are imported + $this->assertContains( + 'The following structures have either been created or altered.', + $import_notice + ); + $this->assertContains( + 'Go to database: `ODS_DB`', + $import_notice + ); + $this->assertContains( + 'Edit settings for `ODS_DB`', + $import_notice + ); + $this->assertContains( + 'Go to table: `pma_bookmark`', + $import_notice + ); + $this->assertContains( + 'Edit settings for `pma_bookmark`', + $import_notice + ); + + //asset that the import process is finished + $this->assertEquals( + true, + $GLOBALS['finished'] + ); + } +} + + + diff --git a/test/test_data/db_test.ods b/test/test_data/db_test.ods new file mode 100644 index 0000000000000000000000000000000000000000..8725716c22a5a2a6142f50b75bcbaee53469db9d GIT binary patch literal 2576 zcmZ`*2{aqXAC9=orj|(2x=N@;P)D61u647Co2u3o5{a%Tnqpl=iMvs8wV~S!MYKYR zqjj~8YH2A-M4hb^EoxicbpP-Fy7k`9yqS43@Au7{@69*!{aoz1dB6YwKmcHM;gxwR z*5HyFX9oLc1po*S4G$v3Mg;M8CJF-N1b8|~Sf!D)6r?R?Z%se4IKpQqrWWk$4i`*D++B45N4qpbz= zsl4*4XRlNtIlfo zt!eV3bQW_7HSzNU=7yb8noI}g{$`vZ5pZ{cWP4qvtcrw~aP5sVQr5Dq&r5)m@Z-T$ zj3LjtplivuJC1jnWDzH>AhTK(X4s|$*d#UI0N!!wbv;0_$uaBqcOI?Z^xSa44ZLK?m1z8+&&yPe3c7)Ja)d}?flM-X0}mZ9#MGk0vKd1pps zQ@l#?IqspGDsj~0wOXT}mm!YjXrQ)adGR9uva>)|?}@FLq|Md(gxU1gQ&{7Z2^rF> z@iRO6WA%qTG}`-JBu9pYUV6=TNdxNcu-?Ew2eUSpno*xaf(8oawlc8(qm-FRlINof zs*#d^>@qB5Njg&nBwjowU*3q3)3Q<9cSHF?%z~zR$|hu{IdJRP?Mp^6kxlrD8zQnL zf$=XoKMox?FJbnbU=^JDRIc(B@S{NfNa7>*afDIB5s3h26;ZwD2blEttdw~Y2?zeQqZxVWKUG6y*!jqJtR>eG7!&t+(*VEVrn2nT6}Lb5nD?7yBl~nWrg+{P8dn{42~TZeD3FWL;Wq z*JWD!>>cgfp$fsRUK`85t3otOl0^;@2l~$!w(YGlSNMKpE9?j4^XCBo6h#4m101%I zgjj4)T!N8dE~DLkf{jleFgq4F6pbVdW+J`ZTyeXgBhVONMQ zWexSLQmh6*t}m3}cII+TggP(wyj`>iX8lS^w;-S+47 z8r`<=lbSY5ZsoRazw_oAFBy@ks5m7a@FcukUCj6m2;HN;C8JZTH~i5vqx zi|TeF>LW-gkjs=VfND4Om7X~BDLF~uVrG)f(sS}d%Q>KyH|kxh9*v*rE;Qz^%|;_E zLw=_H+2vFd8e2O#G%NMU%l9-RDRu=c@rFko+G#4MF4drYbQWrjyn29x{@}u~^oXaY^C;IXm zN4ByMX6j}kTFkAEUgmMHH&nEYp_}l0JOJbk& zEr35jLR7CSgs z@&UEX9e)hnU&8%>0M}c|=0-eQa(;$P9d99;J-f(Mm+H>bfT#2GKLjOqF?L~PVY5>9 zOE8{r?rC!)_*RJhwR<-m#ZC_69mGhs#(Aw8JcsROeefplJ539ydS09M#WB?1UMHuM~9wx%k%((?!cUTR(Nzq}!?+6qx-;rWe zG&a-xe4CEG7YCDwg$gHS4a16?WZy#6+TPuuoA`*)jt8wH>*o9=EqpxbH&bq2^kL%G=X^TGZR)$`x~JMG7dh-ZATxiyU!mL zvEJtP>Oy8RP2`4AQA%@CRkUdiv22=@&~iUPCba8%)LFNu%pR^y*5iXOjHXWL{2oz3 zXuH}IR;P9KV_MI%k<{VsSj9Wr#k%$J;(HpyEYlzVA#A;*4}gTiq3Hbe@_JM>Rbt_dgFft%^!kFR@V>e5WjF^ZYnX za>*&_?lycWqGfS(3Z3gY-uY`&^2PBYkxx%L-)v5;F$uK`w30t_2LbQ9Q57AlQpU{34*OT6x;Pdn-P_~YM0H`oL;<({Wo&| zo!f9&bBf$Q{r5~~KWcye^1twJC?u!-E1TI5-0y4OfsveJ{om#GqxSp5chqU_f4jwg g-2VIgj$7vckK1*z=jHnr#>=U49P@qk&3yrX1HOq~l>h($ literal 0 HcmV?d00001 From f818a5dd689c8a867af4ba567dcd025eb300be10 Mon Sep 17 00:00:00 2001 From: adamgsoc2013 Date: Sat, 29 Jun 2013 23:10:18 +0800 Subject: [PATCH 2/3] fix the assert failure --- test/classes/PMA_DisplayResults_test.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/classes/PMA_DisplayResults_test.php b/test/classes/PMA_DisplayResults_test.php index 24fb2bdb5d..bc2c444884 100644 --- a/test/classes/PMA_DisplayResults_test.php +++ b/test/classes/PMA_DisplayResults_test.php @@ -442,7 +442,7 @@ class PMA_DisplayResults_Test extends PHPUnit_Framework_TestCase 41, '123', false, - '333' + '310' ) ); } From 3138f18769dc5ae48ffcef5b5ae961f7526cf9ea Mon Sep 17 00:00:00 2001 From: adamgsoc2013 Date: Mon, 1 Jul 2013 21:38:52 +0800 Subject: [PATCH 3/3] using OpenOffice ODS file for importing ods testing --- libraries/plugins/import/ImportOds.class.php | 3 --- test/classes/plugin/import/ImportOds_test.php | 4 ++-- test/test_data/db_test.ods | Bin 2576 -> 7174 bytes 3 files changed, 2 insertions(+), 5 deletions(-) diff --git a/libraries/plugins/import/ImportOds.class.php b/libraries/plugins/import/ImportOds.class.php index d0911d779c..9bf02a2b3b 100644 --- a/libraries/plugins/import/ImportOds.class.php +++ b/libraries/plugins/import/ImportOds.class.php @@ -161,9 +161,6 @@ class ImportOds extends ImportPlugin * result in increased performance without the need to * alter the code in any way. It's basically a freebee. */ - - //fix import warning: simplexml_load_string(): namespace error : Namespace prefix number is not defined - $buffer = str_replace("number:", "number_", $buffer); $xml = simplexml_load_string($buffer, "SimpleXMLElement", LIBXML_COMPACT); unset($buffer); diff --git a/test/classes/plugin/import/ImportOds_test.php b/test/classes/plugin/import/ImportOds_test.php index 1ccf46b9db..51ce3df8b8 100644 --- a/test/classes/plugin/import/ImportOds_test.php +++ b/test/classes/plugin/import/ImportOds_test.php @@ -69,7 +69,7 @@ class ImportOds_Test extends PHPUnit_Framework_TestCase $GLOBALS['import_text'] = $result["data"]; $GLOBALS['compression'] = 'application/zip'; $GLOBALS['read_multiply'] = 10; - $GLOBALS['import_type'] = 'Xml'; + $GLOBALS['import_type'] = 'ods'; $GLOBALS['import_handle'] = @fopen($GLOBALS['import_file'], 'r'); //varible for Ods @@ -147,7 +147,7 @@ class ImportOds_Test extends PHPUnit_Framework_TestCase $sql_query ); $this->assertContains( - "INSERT INTO `ODS_DB`.`pma_bookmark` (`A`, `B`, `C`, `D`, `E`) VALUES (1, 'dbbase', '', 'ddd', '')", + "INSERT INTO `ODS_DB`.`pma_bookmark` (`A`, `B`, `C`, `D`) VALUES (1, 'dbbase', NULL, 'ddd');", $sql_query ); diff --git a/test/test_data/db_test.ods b/test/test_data/db_test.ods index 8725716c22a5a2a6142f50b75bcbaee53469db9d..8b3482600765ce3281b3d4c42cbad3ce91107c31 100644 GIT binary patch literal 7174 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