2 /*********************************************************************************
3 * SugarCRM Community Edition is a customer relationship management program developed by
4 * SugarCRM, Inc. Copyright (C) 2004-2011 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 public function setUp()
44 $GLOBALS['current_user'] = SugarTestUserUtilities::createAnonymousUser();
47 public function tearDown()
49 SugarTestImportUtilities::removeAllCreatedFiles();
50 SugarTestUserUtilities::removeAllCreatedAnonymousUsers();
51 unset($GLOBALS['current_user']);
57 public function testFileImportNoEnclosers()
59 $file = SugarTestImportUtilities::createFile(2,1);
60 $importFile = new ImportFile($file,',','', TRUE, FALSE);
61 $row = $importFile->getNextRow();
62 $this->assertEquals($row, array('foo00'));
63 $row = $importFile->getNextRow();
64 $this->assertEquals($row,array('foo10'));
67 public function testLoadNonExistantFile()
69 $importFile = new ImportFile($GLOBALS['sugar_config']['import_dir'].'/thisfileisntthere'.date("YmdHis").'.csv',',','"');
70 $this->assertFalse($importFile->fileExists());
73 public function testLoadGoodFile()
75 $file = SugarTestImportUtilities::createFile(2,1);
76 $importFile = new ImportFile($file,',','"', TRUE, FALSE);
77 $this->assertTrue($importFile->fileExists());
83 public function testLoadFileWithByteOrderMark()
85 $sample_file = $GLOBALS['sugar_config']['upload_dir'].'/Bug39494ImportFile.txt';
86 copy('tests/modules/Import/Bug39494ImportFile.txt', $sample_file);
87 $importFile = new ImportFile($sample_file,"\t",'',false);
88 $this->assertTrue($importFile->fileExists());
89 $row = $importFile->getNextRow();
90 $this->assertEquals($row,array('name','city'));
91 $row = $importFile->getNextRow();
92 $this->assertEquals($row,array('tester1','wuhan'));
96 public function testGetNextRow()
98 $file = SugarTestImportUtilities::createFile(3,2);
99 $importFile = new ImportFile($file,',','"', TRUE, FALSE);
101 $row = $importFile->getNextRow();
102 $this->assertEquals(array("foo00","foo01"),$row);
103 $row = $importFile->getNextRow();
104 $this->assertEquals(array("foo10","foo11"),$row);
105 $row = $importFile->getNextRow();
106 $this->assertEquals(array("foo20","foo21"),$row);
112 public function testGetNextRowWithEOL()
114 $file = SugarTestImportUtilities::createFileWithEOL(1, 1);
115 $importFile = new ImportFile($file,',','"', TRUE, FALSE);
116 $row = $importFile->getNextRow();
117 // both \r\n and \n should be properly replaced with PHP_EOL
118 $this->assertEquals(array("start0".PHP_EOL."0".PHP_EOL."end"), $row);
121 public function testLoadEmptyFile()
123 $emptyFile = $GLOBALS['sugar_config']['import_dir'].'/empty'.date("YmdHis").'.csv';
124 file_put_contents($emptyFile,'');
126 $importFile = new ImportFile($emptyFile,',','"',false);
128 $this->assertFalse($importFile->getNextRow());
130 $importFile = new ImportFile($emptyFile,',','',false);
132 $this->assertFalse($importFile->getNextRow());
137 public function testDeleteFileOnDestroy()
139 $file = SugarTestImportUtilities::createFile(3,2);
140 $importFile = new ImportFile($file,',','"',true, FALSE);
144 $this->assertFalse(is_file($file));
147 public function testNotDeleteFileOnDestroy()
149 $file = SugarTestImportUtilities::createFile(3,2);
150 $importFile = new ImportFile($file,',','"',false);
154 $this->assertTrue(is_file($file));
157 public function testGetFieldCount()
159 $file = SugarTestImportUtilities::createFile(3,2);
160 $importFile = new ImportFile($file,',','"',TRUE, FALSE);
162 $importFile->getNextRow();
163 $this->assertEquals(2,$importFile->getFieldCount());
166 public function testMarkRowAsDuplicate()
168 $file = SugarTestImportUtilities::createFile(3,2);
169 $importFile = new ImportFile($file,',','"', TRUE, FALSE);
171 $row = $importFile->getNextRow();
172 $importFile->markRowAsDuplicate();
174 $fp = sugar_fopen(ImportCacheFiles::getDuplicateFileName(),'r');
175 $duperow = fgetcsv($fp);
178 $this->assertEquals($row,$duperow);
181 public function testWriteError()
183 $file = SugarTestImportUtilities::createFile(3,2);
184 $importFile = new ImportFile($file,',','"', TRUE, FALSE);
186 $row = $importFile->getNextRow();
187 $importFile->writeError('Some Error','field1','foo');
189 $fp = sugar_fopen(ImportCacheFiles::getErrorFileName(),'r');
190 $errorrow = fgetcsv($fp);
193 $this->assertEquals(array('Some Error','field1','foo',1),$errorrow);
195 $fp = sugar_fopen(ImportCacheFiles::getErrorRecordsWithoutErrorFileName(),'r');
196 $errorrecordrow = fgetcsv($fp);
199 $this->assertEquals($row,$errorrecordrow);
202 public function testWriteErrorRecord()
204 $file = SugarTestImportUtilities::createFile(3,2);
205 $importFile = new ImportFile($file,',','"', TRUE, FALSE);
207 $row = $importFile->getNextRow();
208 $importFile->writeErrorRecord();
210 $fp = sugar_fopen(ImportCacheFiles::getErrorRecordsWithoutErrorFileName(),'r');
211 $errorrecordrow = fgetcsv($fp);
214 $this->assertEquals($row,$errorrecordrow);
217 public function testWriteStatus()
219 $file = SugarTestImportUtilities::createFile(3,2);
220 $importFile = new ImportFile($file,',','"', TRUE, FALSE);
222 $importFile->getNextRow();
223 $importFile->writeError('Some Error','field1','foo');
224 $importFile->getNextRow();
225 $importFile->markRowAsDuplicate();
226 $importFile->getNextRow();
227 $importFile->markRowAsImported();
228 $importFile->writeStatus();
230 $fp = sugar_fopen(ImportCacheFiles::getStatusFileName(),'r');
231 $statusrow = fgetcsv($fp);
234 $this->assertEquals(array(3,1,1,1,0,$file),$statusrow);
237 public function testWriteStatusWithTwoErrorsInOneRow()
239 $file = SugarTestImportUtilities::createFile(3,2);
240 $importFile = new ImportFile($file,',','"', TRUE, FALSE);
242 $row = $importFile->getNextRow();
243 $importFile->writeError('Some Error','field1','foo');
244 $importFile->writeError('Some Error','field1','foo');
245 $importFile->getNextRow();
246 $importFile->markRowAsImported();
247 $importFile->getNextRow();
248 $importFile->markRowAsImported();
249 $importFile->writeStatus();
251 $fp = sugar_fopen(ImportCacheFiles::getStatusFileName(),'r');
252 $statusrow = fgetcsv($fp);
255 $this->assertEquals(array(3,1,0,2,0,$file),$statusrow);
257 $fp = sugar_fopen(ImportCacheFiles::getErrorRecordsWithoutErrorFileName(),'r');
258 $errorrecordrow = fgetcsv($fp);
260 $this->assertEquals($row,$errorrecordrow);
262 $this->assertFalse(fgetcsv($fp),'Should be only 1 record in the csv file');
267 public function testWriteStatusWithTwoUpdatedRecords()
269 $file = SugarTestImportUtilities::createFile(3,2);
270 $importFile = new ImportFile($file,',','"', TRUE, FALSE);
272 $row = $importFile->getNextRow();
273 $importFile->markRowAsImported(false);
274 $importFile->getNextRow();
275 $importFile->markRowAsImported();
276 $importFile->getNextRow();
277 $importFile->markRowAsImported();
278 $importFile->writeStatus();
280 $fp = sugar_fopen(ImportCacheFiles::getStatusFileName(),'r');
281 $statusrow = fgetcsv($fp);
284 $this->assertEquals(array(3,0,0,2,1,$file),$statusrow);
287 public function testWriteRowToLastImport()
289 $file = SugarTestImportUtilities::createFile(3,2);
290 $importFile = new ImportFile($file,',','"');
291 $record = $importFile->writeRowToLastImport("Tests","Test","TestRunner");
294 FROM users_last_import
295 WHERE assigned_user_id = '{$GLOBALS['current_user']->id}'
296 AND import_module = 'Tests'
297 AND bean_type = 'Test'
298 AND bean_id = 'TestRunner'
302 $result = $GLOBALS['db']->query($query);
304 $this->assertNotNull($GLOBALS['db']->fetchByAssoc($result));
306 $query = "DELETE FROM users_last_import
307 WHERE assigned_user_id = '{$GLOBALS['current_user']->id}'
308 AND import_module = 'Tests'
309 AND bean_type = 'Test'
310 AND bean_id = 'TestRunner'
313 $GLOBALS['db']->query($query);
316 public function providerEncodingData()
319 array('TestCharset.csv', 'UTF-8'),
320 array('TestCharset2.csv', 'ISO-8859-1'),
325 * @dataProvider providerEncodingData
327 public function testCharsetDetection($file, $encoding) {
328 // create the test file
329 $sample_file = $GLOBALS['sugar_config']['upload_dir'].'/'.$file;
330 copy('tests/modules/Import/'.$file, $sample_file);
332 // auto detect charset
333 $importFile = new ImportFile($sample_file, ",", '', false, false);
334 $this->assertTrue($importFile->fileExists());
335 $charset = $importFile->autoDetectCharacterSet();
336 $this->assertEquals($encoding, $charset, 'detected char encoding is incorrect.');
339 unlink($sample_file);
342 public function providerRowCountData()
345 array('TestCharset.csv', 2, false),
346 array('TestCharset2.csv', 11, true),
347 array('TestCharset2.csv', 12, false),
352 * @dataProvider providerRowCountData
354 public function testRowCount($file, $count, $hasHeader) {
355 // create the test file
356 $sample_file = $GLOBALS['sugar_config']['upload_dir'].'/'.$file;
357 copy('tests/modules/Import/'.$file, $sample_file);
359 $importFile = new ImportFile($sample_file, ",", '', false, false);
360 $this->assertTrue($importFile->fileExists());
361 $importFile->setHeaderRow($hasHeader);
362 $c = $importFile->getTotalRecordCount();
363 $this->assertEquals($count, $c, 'incorrect row count.');
366 unlink($sample_file);
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);
385 $importFile = new ImportFile($sample_file, ",", '"', false, false);
386 $this->assertTrue($importFile->fileExists());
387 $c = $importFile->getNextRow();
388 $c = $importFile->getFieldCount();
389 $this->assertEquals($count, $c, 'incorrect row count.');
392 unlink($sample_file);
395 public function providerLineCountData()
398 array('TestCharset.csv', 2),
399 array('TestCharset2.csv', 12),
404 * @dataProvider providerLineCountData
406 public function testLineCount($file, $count) {
407 // create the test file
408 $sample_file = $GLOBALS['sugar_config']['upload_dir'].'/'.$file;
409 copy('tests/modules/Import/'.$file, $sample_file);
411 $importFile = new ImportFile($sample_file, ",", '"', false, false);
412 $this->assertTrue($importFile->fileExists());
413 $c = $importFile->getNumberOfLinesInfile();
414 $this->assertEquals($count, $c, 'incorrect row count.');
417 unlink($sample_file);
420 public function providerDateFormatData()
423 array('TestCharset.csv', 'd/m/Y'),
424 array('TestCharset2.csv', 'm/d/Y'),
429 * @dataProvider providerDateFormatData
431 public function testDateFormat($file, $format) {
432 // create the test file
433 $sample_file = $GLOBALS['sugar_config']['upload_dir'].'/'.$file;
434 copy('tests/modules/Import/'.$file, $sample_file);
436 $importFile = new ImportFile($sample_file, ",", '"', false, false);
437 $this->assertTrue($importFile->fileExists());
438 $ret = $importFile->autoDetectCSVProperties();
439 $this->assertTrue($ret, 'Failed to auto detect properties.');
440 $c = $importFile->getDateFormat();
441 $this->assertEquals($format, $c, 'incorrect date format.');
444 unlink($sample_file);
447 public function providerTimeFormatData()
450 array('TestCharset.csv', 'h:ia'),
451 array('TestCharset2.csv', 'H:i'),
456 * @dataProvider providerTimeFormatData
458 public function testTimeFormat($file, $format) {
459 // create the test file
460 $sample_file = $GLOBALS['sugar_config']['upload_dir'].'/'.$file;
461 copy('tests/modules/Import/'.$file, $sample_file);
463 $importFile = new ImportFile($sample_file, ",", '"', false, false);
464 $this->assertTrue($importFile->fileExists());
465 $ret = $importFile->autoDetectCSVProperties();
466 $this->assertTrue($ret, 'Failed to auto detect properties.');
467 $c = $importFile->getTimeFormat();
468 $this->assertEquals($format, $c, 'incorrect time format.');
471 unlink($sample_file);
477 public function testTabDelimiter() {
478 // create the test file
479 $sample_file = $GLOBALS['sugar_config']['upload_dir'].'/TestCharset.csv';
480 copy('tests/modules/Import/TestCharset.csv', $sample_file);
482 // use '\t' to simulate the bug
483 $importFile = new ImportFile($sample_file, '\t', '"', false, false);
484 $this->assertTrue($importFile->fileExists());
485 $c = $importFile->getNextRow();
486 $this->assertTrue(is_array($c), 'incorrect return type.');
487 $this->assertEquals(1, count($c), 'incorrect array count.');
490 unlink($sample_file);