2 /*********************************************************************************
3 * SugarCRM Community Edition is a customer relationship management program developed by
4 * SugarCRM, Inc. Copyright (C) 2004-2013 SugarCRM Inc.
6 * This program is free software; you can redistribute it and/or modify it under
7 * the terms of the GNU Affero General Public License version 3 as published by the
8 * Free Software Foundation with the addition of the following permission added
9 * to Section 15 as permitted in Section 7(a): FOR ANY PART OF THE COVERED WORK
10 * IN WHICH THE COPYRIGHT IS OWNED BY SUGARCRM, SUGARCRM DISCLAIMS THE WARRANTY
11 * OF NON INFRINGEMENT OF THIRD PARTY RIGHTS.
13 * This program is distributed in the hope that it will be useful, but WITHOUT
14 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
15 * FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
18 * You should have received a copy of the GNU Affero General Public License along with
19 * this program; if not, see http://www.gnu.org/licenses or write to the Free
20 * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
23 * You can contact SugarCRM, Inc. headquarters at 10050 North Wolfe Road,
24 * SW2-130, Cupertino, CA 95014, USA. or at email address contact@sugarcrm.com.
26 * The interactive user interfaces in modified source and object code versions
27 * of this program must display Appropriate Legal Notices, as required under
28 * Section 5 of the GNU Affero General Public License version 3.
30 * In accordance with Section 7(b) of the GNU Affero General Public License version 3,
31 * these Appropriate Legal Notices must retain the display of the "Powered by
32 * SugarCRM" logo. If the display of the logo is not reasonably feasible for
33 * technical reasons, the Appropriate Legal Notices must display the words
34 * "Powered by SugarCRM".
35 ********************************************************************************/
38 require_once('modules/Import/sources/ImportFile.php');
40 class ImportFileTest extends Sugar_PHPUnit_Framework_TestCase
42 protected $unlink = array();
44 public function setUp()
46 $GLOBALS['current_user'] = SugarTestUserUtilities::createAnonymousUser();
49 public function tearDown()
51 SugarTestImportUtilities::removeAllCreatedFiles();
52 SugarTestUserUtilities::removeAllCreatedAnonymousUsers();
53 foreach($this->unlink as $file) {
56 unset($GLOBALS['current_user']);
62 public function testFileImportNoEnclosers()
64 $file = SugarTestImportUtilities::createFile(2,1);
65 $importFile = new ImportFile($file,',','', TRUE, FALSE);
66 $row = $importFile->getNextRow();
67 $this->assertEquals($row, array('foo00'));
68 $row = $importFile->getNextRow();
69 $this->assertEquals($row,array('foo10'));
72 public function testLoadNonExistantFile()
74 $importFile = new ImportFile(ImportCacheFiles::getImportDir().'/thisfileisntthere'.date("YmdHis").'.csv',',','"');
75 $this->assertFalse($importFile->fileExists());
78 public function testLoadGoodFile()
80 $file = SugarTestImportUtilities::createFile(2,1);
81 $importFile = new ImportFile($file,',','"', TRUE, FALSE);
82 $this->assertTrue($importFile->fileExists());
88 public function testLoadFileWithByteOrderMark()
90 $sample_file = 'upload://Bug39494ImportFile.txt';
91 copy('tests/modules/Import/Bug39494ImportFile.txt', $sample_file);
92 $this->unlink[] = $sample_file;
93 $importFile = new ImportFile($sample_file,"\t",'',false);
94 $this->assertTrue($importFile->fileExists());
95 $row = $importFile->getNextRow();
96 $this->assertEquals($row,array('name','city'));
97 $row = $importFile->getNextRow();
98 $this->assertEquals($row,array('tester1','wuhan'));
101 public function testGetNextRow()
103 $file = SugarTestImportUtilities::createFile(3,2);
104 $importFile = new ImportFile($file,',','"', TRUE, FALSE);
106 $row = $importFile->getNextRow();
107 $this->assertEquals(array("foo00","foo01"),$row);
108 $row = $importFile->getNextRow();
109 $this->assertEquals(array("foo10","foo11"),$row);
110 $row = $importFile->getNextRow();
111 $this->assertEquals(array("foo20","foo21"),$row);
117 public function testGetNextRowWithEOL()
119 $file = SugarTestImportUtilities::createFileWithEOL(1, 1);
120 $importFile = new ImportFile($file,',','"', TRUE, FALSE);
121 $row = $importFile->getNextRow();
122 // both \r\n and \n should be properly replaced with PHP_EOL
123 $this->assertEquals(array("start0".PHP_EOL."0".PHP_EOL."end"), $row);
126 public function testLoadEmptyFile()
128 $emptyFile = ImportCacheFiles::getImportDir().'/empty'.date("YmdHis").'.csv';
129 file_put_contents($emptyFile,'');
130 $this->unlink[] = $emptyFile;
132 $importFile = new ImportFile($emptyFile,',','"',false);
134 $this->assertFalse($importFile->getNextRow());
136 $importFile = new ImportFile($emptyFile,',','',false);
138 $this->assertFalse($importFile->getNextRow());
141 public function testDeleteFileOnDestroy()
143 $file = SugarTestImportUtilities::createFile(3,2);
144 $importFile = new ImportFile($file,',','"',true, FALSE);
148 $this->assertFalse(is_file($file));
151 public function testNotDeleteFileOnDestroy()
153 $file = SugarTestImportUtilities::createFile(3,2);
154 $importFile = new ImportFile($file,',','"',false);
158 $this->assertTrue(is_file($file));
161 public function testGetFieldCount()
163 $file = SugarTestImportUtilities::createFile(3,2);
164 $importFile = new ImportFile($file,',','"',TRUE, FALSE);
166 $importFile->getNextRow();
167 $this->assertEquals(2,$importFile->getFieldCount());
170 public function testMarkRowAsDuplicate()
172 $file = SugarTestImportUtilities::createFile(3,2);
173 $importFile = new ImportFile($file,',','"', TRUE, FALSE);
175 $row = $importFile->getNextRow();
176 $importFile->markRowAsDuplicate();
178 $fp = sugar_fopen(ImportCacheFiles::getDuplicateFileName(),'r');
179 $duperow = fgetcsv($fp);
182 $this->assertEquals($row,$duperow);
185 public function testWriteError()
187 $file = SugarTestImportUtilities::createFile(3,2);
188 $importFile = new ImportFile($file,',','"', TRUE, FALSE);
190 $row = $importFile->getNextRow();
191 $importFile->writeError('Some Error','field1','foo');
193 $fp = sugar_fopen(ImportCacheFiles::getErrorFileName(),'r');
194 $errorrow = fgetcsv($fp);
197 $this->assertEquals(array('Some Error','field1','foo',1),$errorrow);
199 $fp = sugar_fopen(ImportCacheFiles::getErrorRecordsWithoutErrorFileName(),'r');
200 $errorrecordrow = fgetcsv($fp);
203 $this->assertEquals($row,$errorrecordrow);
206 public function testWriteErrorRecord()
208 $file = SugarTestImportUtilities::createFile(3,2);
209 $importFile = new ImportFile($file,',','"', TRUE, FALSE);
211 $row = $importFile->getNextRow();
212 $importFile->writeErrorRecord();
214 $fp = sugar_fopen(ImportCacheFiles::getErrorRecordsWithoutErrorFileName(),'r');
215 $errorrecordrow = fgetcsv($fp);
218 $this->assertEquals($row,$errorrecordrow);
221 public function testWriteStatus()
223 $file = SugarTestImportUtilities::createFile(3,2);
224 $importFile = new ImportFile($file,',','"', TRUE, FALSE);
226 $importFile->getNextRow();
227 $importFile->writeError('Some Error','field1','foo');
228 $importFile->getNextRow();
229 $importFile->markRowAsDuplicate();
230 $importFile->getNextRow();
231 $importFile->markRowAsImported();
232 $importFile->writeStatus();
234 $fp = sugar_fopen(ImportCacheFiles::getStatusFileName(),'r');
235 $statusrow = fgetcsv($fp);
238 $this->assertEquals(array(3,1,1,1,0,$file),$statusrow);
241 public function testWriteStatusWithTwoErrorsInOneRow()
243 $file = SugarTestImportUtilities::createFile(3,2);
244 $importFile = new ImportFile($file,',','"', TRUE, FALSE);
246 $row = $importFile->getNextRow();
247 $importFile->writeError('Some Error','field1','foo');
248 $importFile->writeError('Some Error','field1','foo');
249 $importFile->getNextRow();
250 $importFile->markRowAsImported();
251 $importFile->getNextRow();
252 $importFile->markRowAsImported();
253 $importFile->writeStatus();
255 $fp = sugar_fopen(ImportCacheFiles::getStatusFileName(),'r');
256 $statusrow = fgetcsv($fp);
259 $this->assertEquals(array(3,1,0,2,0,$file),$statusrow);
261 $fp = sugar_fopen(ImportCacheFiles::getErrorRecordsWithoutErrorFileName(),'r');
262 $errorrecordrow = fgetcsv($fp);
264 $this->assertEquals($row,$errorrecordrow);
266 $this->assertFalse(fgetcsv($fp),'Should be only 1 record in the csv file');
271 public function testWriteStatusWithTwoUpdatedRecords()
273 $file = SugarTestImportUtilities::createFile(3,2);
274 $importFile = new ImportFile($file,',','"', TRUE, FALSE);
276 $row = $importFile->getNextRow();
277 $importFile->markRowAsImported(false);
278 $importFile->getNextRow();
279 $importFile->markRowAsImported();
280 $importFile->getNextRow();
281 $importFile->markRowAsImported();
282 $importFile->writeStatus();
284 $fp = sugar_fopen(ImportCacheFiles::getStatusFileName(),'r');
285 $statusrow = fgetcsv($fp);
288 $this->assertEquals(array(3,0,0,2,1,$file),$statusrow);
291 public function testWriteRowToLastImport()
293 $file = SugarTestImportUtilities::createFile(3,2);
294 $importFile = new ImportFile($file,',','"');
295 $record = $importFile->writeRowToLastImport("Tests","Test","TestRunner");
298 FROM users_last_import
299 WHERE assigned_user_id = '{$GLOBALS['current_user']->id}'
300 AND import_module = 'Tests'
301 AND bean_type = 'Test'
302 AND bean_id = 'TestRunner'
306 $result = $GLOBALS['db']->query($query);
308 $this->assertNotNull($GLOBALS['db']->fetchByAssoc($result));
310 $query = "DELETE FROM users_last_import
311 WHERE assigned_user_id = '{$GLOBALS['current_user']->id}'
312 AND import_module = 'Tests'
313 AND bean_type = 'Test'
314 AND bean_id = 'TestRunner'
317 $GLOBALS['db']->query($query);
320 public function providerEncodingData()
323 array('TestCharset.csv', 'UTF-8'),
324 array('TestCharset2.csv', 'ISO-8859-1'),
329 * @dataProvider providerEncodingData
331 public function testCharsetDetection($file, $encoding) {
332 // create the test file
333 $sample_file = $GLOBALS['sugar_config']['upload_dir'].'/'.$file;
334 copy('tests/modules/Import/'.$file, $sample_file);
335 $this->unlink[] = $sample_file;
337 // auto detect charset
338 $importFile = new ImportFile($sample_file, ",", '', false, false);
339 $this->assertTrue($importFile->fileExists());
340 $charset = $importFile->autoDetectCharacterSet();
341 $this->assertEquals($encoding, $charset, 'detected char encoding is incorrect.');
344 public function providerRowCountData()
347 array('TestCharset.csv', 2, false),
348 array('TestCharset2.csv', 11, true),
349 array('TestCharset2.csv', 12, false),
354 * @dataProvider providerRowCountData
356 public function testRowCount($file, $count, $hasHeader) {
357 // create the test file
358 $sample_file = $GLOBALS['sugar_config']['upload_dir'].'/'.$file;
359 copy('tests/modules/Import/'.$file, $sample_file);
360 $this->unlink[] = $sample_file;
362 $importFile = new ImportFile($sample_file, ",", '', false, false);
363 $this->assertTrue($importFile->fileExists());
364 $importFile->setHeaderRow($hasHeader);
365 $c = $importFile->getTotalRecordCount();
366 $this->assertEquals($count, $c, 'incorrect row count.');
369 public function providerFieldCountData()
372 array('TestCharset.csv', 2),
373 array('TestCharset2.csv', 5),
378 * @dataProvider providerFieldCountData
380 public function testFieldCount($file, $count) {
381 // create the test file
382 $sample_file = $GLOBALS['sugar_config']['upload_dir'].'/'.$file;
383 copy('tests/modules/Import/'.$file, $sample_file);
384 $this->unlink[] = $sample_file;
386 $importFile = new ImportFile($sample_file, ",", '"', false, false);
387 $this->assertTrue($importFile->fileExists());
388 $c = $importFile->getNextRow();
389 $c = $importFile->getFieldCount();
390 $this->assertEquals($count, $c, 'incorrect row count.');
393 public function providerLineCountData()
396 array('TestCharset.csv', 2),
397 array('TestCharset2.csv', 12),
402 * @dataProvider providerLineCountData
404 public function testLineCount($file, $count) {
405 // create the test file
406 $sample_file = $GLOBALS['sugar_config']['upload_dir'].'/'.$file;
407 copy('tests/modules/Import/'.$file, $sample_file);
408 $this->unlink[] = $sample_file;
410 $importFile = new ImportFile($sample_file, ",", '"', false, false);
411 $this->assertTrue($importFile->fileExists());
412 $c = $importFile->getNumberOfLinesInfile();
413 $this->assertEquals($count, $c, 'incorrect row count.');
416 public function providerDateFormatData()
419 array('TestCharset.csv', 'd/m/Y'),
420 array('TestCharset2.csv', 'm/d/Y'),
425 * @dataProvider providerDateFormatData
427 public function testDateFormat($file, $format) {
428 // create the test file
429 $sample_file = $GLOBALS['sugar_config']['upload_dir'].'/'.$file;
430 copy('tests/modules/Import/'.$file, $sample_file);
431 $this->unlink[] = $sample_file;
433 $importFile = new ImportFile($sample_file, ",", '"', false, false);
434 $this->assertTrue($importFile->fileExists());
435 $ret = $importFile->autoDetectCSVProperties();
436 $this->assertTrue($ret, 'Failed to auto detect properties.');
437 $c = $importFile->getDateFormat();
438 $this->assertEquals($format, $c, 'incorrect date format.');
441 public function providerTimeFormatData()
444 array('TestCharset.csv', 'h:ia'),
445 array('TestCharset2.csv', 'H:i'),
450 * @dataProvider providerTimeFormatData
452 public function testTimeFormat($file, $format) {
453 // create the test file
454 $sample_file = $GLOBALS['sugar_config']['upload_dir'].'/'.$file;
455 copy('tests/modules/Import/'.$file, $sample_file);
456 $this->unlink[] = $sample_file;
458 $importFile = new ImportFile($sample_file, ",", '"', false, false);
459 $this->assertTrue($importFile->fileExists());
460 $ret = $importFile->autoDetectCSVProperties();
461 $this->assertTrue($ret, 'Failed to auto detect properties.');
462 $c = $importFile->getTimeFormat();
463 $this->assertEquals($format, $c, 'incorrect time format.');
469 public function testTabDelimiter() {
470 // create the test file
471 $sample_file = $GLOBALS['sugar_config']['upload_dir'].'/TestCharset.csv';
472 copy('tests/modules/Import/TestCharset.csv', $sample_file);
474 // use '\t' to simulate the bug
475 $importFile = new ImportFile($sample_file, '\t', '"', false, false);
476 $this->assertTrue($importFile->fileExists());
477 $c = $importFile->getNextRow();
478 $this->assertTrue(is_array($c), 'incorrect return type.');
479 $this->assertEquals(1, count($c), 'incorrect array count.');
482 $this->unlink[] = $sample_file;