PageRenderTime 59ms CodeModel.GetById 24ms RepoModel.GetById 1ms app.codeStats 0ms

/Unit Tests/UnitTests.m

http://github.com/davedelong/CHCSVParser
Objective C | 667 lines | 544 code | 95 blank | 28 comment | 16 complexity | f635a0723b280f50cef7b7f2158dd52f MD5 | raw file
  1. //
  2. // UnitTests.m
  3. // CHCSVParser
  4. /**
  5. Copyright (c) 2014 Dave DeLong
  6. Permission is hereby granted, free of charge, to any person obtaining a copy
  7. of this software and associated documentation files (the "Software"), to deal
  8. in the Software without restriction, including without limitation the rights
  9. to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  10. copies of the Software, and to permit persons to whom the Software is
  11. furnished to do so, subject to the following conditions:
  12. The above copyright notice and this permission notice shall be included in
  13. all copies or substantial portions of the Software.
  14. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  15. IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  16. FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  17. AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  18. LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  19. OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  20. THE SOFTWARE.
  21. **/
  22. #import "UnitTests.h"
  23. #import "UnitTestContent.h"
  24. #import "CHCSVParser.h"
  25. #define TEST_ARRAYS(_actual, _expected) do {\
  26. XCTAssertEqual(_actual.count, _expected.count, @"incorrect number of records"); \
  27. if (_actual.count == _expected.count) { \
  28. for (NSUInteger _record = 0; _record < _actual.count; ++_record) { \
  29. NSArray *_actualRow = _actual[_record]; \
  30. NSArray *_expectedRow = _expected[_record]; \
  31. XCTAssertEqual(_actualRow.count, _expectedRow.count, @"incorrect number of fields on line %lu", _record + 1); \
  32. if (_actualRow.count == _expectedRow.count) { \
  33. for (NSUInteger _field = 0; _field < _actualRow.count; ++_field) { \
  34. id _actualField = _actualRow[_field]; \
  35. id _expectedField = _expectedRow[_field]; \
  36. XCTAssertEqualObjects(_actualField, _expectedField, @"mismatched field #%lu on line %lu", _field, _record + 1); \
  37. if ([_actualField isEqual:_expectedField] == NO) { \
  38. NSLog(@"expected data: %@", [_expectedField dataUsingEncoding:NSUTF8StringEncoding]); \
  39. NSLog(@"actual data: %@", [_actualField dataUsingEncoding:NSUTF8StringEncoding]); \
  40. } \
  41. } \
  42. } \
  43. } \
  44. } \
  45. } while(0)
  46. #define TEST(_csv, _expected, ...) do {\
  47. NSUInteger _optionList[] = {0, ##__VA_ARGS__}; \
  48. NSUInteger _option = _optionList[(sizeof(_optionList)/sizeof(NSUInteger)) == 2 ? 1 : 0]; \
  49. NSArray *_parsed = [(_csv) CSVComponentsWithOptions:(_option)]; \
  50. TEST_ARRAYS(_parsed, _expected); \
  51. } while(0)
  52. @implementation UnitTests
  53. - (NSURL *)temporaryURLForDelimitedString:(NSString *)string {
  54. static NSURL *temporaryFolder = nil;
  55. static dispatch_once_t onceToken;
  56. dispatch_once(&onceToken, ^{
  57. NSURL *tmp = [NSURL fileURLWithPath:NSTemporaryDirectory()];
  58. tmp = [tmp URLByAppendingPathComponent:@"CHCSVParser" isDirectory:YES];
  59. NSDateFormatter *f = [[NSDateFormatter alloc] init];
  60. f.locale = [NSLocale localeWithLocaleIdentifier:@"en_US_POSIX"];
  61. f.calendar = [NSCalendar calendarWithIdentifier:NSCalendarIdentifierGregorian];
  62. f.timeZone = [NSTimeZone timeZoneForSecondsFromGMT:0];
  63. f.dateFormat = @"yyyy.MM.dd.HH.mm.ss.SSSSS";
  64. NSString *folderName = [f stringFromDate:[NSDate date]];
  65. temporaryFolder = [tmp URLByAppendingPathComponent:folderName isDirectory:YES];
  66. XCTAssertNotNil(temporaryFolder, @"Unable to locate temporary directory");
  67. NSError *error = nil;
  68. BOOL created = [[NSFileManager defaultManager] createDirectoryAtURL:temporaryFolder withIntermediateDirectories:YES attributes:nil error:&error];
  69. XCTAssertTrue(created, @"Unable to create temporary directory (%@)", error);
  70. NSLog(@"Writing files to %@", temporaryFolder);
  71. });
  72. NSString *name = [NSUUID UUID].UUIDString;
  73. NSURL *url = [temporaryFolder URLByAppendingPathComponent:name];
  74. NSError *error = nil;
  75. BOOL written = [string writeToURL:url atomically:YES encoding:NSUTF8StringEncoding error:&error];
  76. XCTAssertTrue(written, @"Unable to write string to temporary folder: %@", error);
  77. return url;
  78. }
  79. - (void)testAvailableEncodings {
  80. const CFStringEncoding *encodings = CFStringGetListOfAvailableEncodings();
  81. while (*encodings != kCFStringEncodingInvalidId) {
  82. CFStringEncoding encoding = *encodings;
  83. NSStringEncoding nsEncoding = CFStringConvertEncodingToNSStringEncoding(encoding);
  84. if (nsEncoding == kCFStringEncodingInvalidId) {
  85. NSLog(@"Invalid: %@", CFStringGetNameOfEncoding(encoding));
  86. } else {
  87. NSData *a = [@"a" dataUsingEncoding:nsEncoding];
  88. NSData *aa = [@"aa" dataUsingEncoding:nsEncoding];
  89. NSData *bom = nil;
  90. if ([a length] * 2 != [aa length]) {
  91. NSUInteger characterLength = [aa length] - [a length];
  92. bom = [a subdataWithRange:NSMakeRange(0, [a length] - characterLength)];
  93. }
  94. NSLog(@"%@: %@", CFStringGetNameOfEncoding(encoding), bom);
  95. }
  96. encodings++;
  97. }
  98. }
  99. - (void)testSimple {
  100. NSString *csv = FIELD1 COMMA FIELD2 COMMA FIELD3;
  101. NSArray *expected = @[@[FIELD1, FIELD2, FIELD3]];
  102. TEST(csv, expected);
  103. }
  104. - (void)testSimpleUTF8 {
  105. NSString *csv = FIELD1 COMMA FIELD2 COMMA FIELD3 COMMA UTF8FIELD4 NEWLINE FIELD1 COMMA FIELD2 COMMA FIELD3 COMMA UTF8FIELD4;
  106. NSArray *expected = @[@[FIELD1, FIELD2, FIELD3, UTF8FIELD4], @[FIELD1, FIELD2, FIELD3, UTF8FIELD4]];
  107. TEST(csv, expected);
  108. }
  109. - (void)testGithubIssue35 {
  110. NSString *tsv = @"1,a" TAB @"1,b" TAB @"1,c" TAB @"1,\"d\"" NEWLINE
  111. @"2,a" TAB @"2,b" TAB @"2,c" TAB @"2,d" NEWLINE
  112. @"3,a" TAB @"3,b" TAB @"3,c" TAB @"3,d" NEWLINE
  113. @"4,a" TAB @"4,b" TAB @"4,c" TAB @"4,d" NEWLINE
  114. @"5,a" TAB @"5,b" TAB @"5,c" TAB @"5,d" NEWLINE
  115. @"6,a" TAB @"6,b" TAB @"6,c" TAB @"6,d" NEWLINE
  116. @"7,a" TAB @"7,b" TAB @"7,c" TAB @"7,d" NEWLINE
  117. @"8,a" TAB @"8,b" TAB @"8,c" TAB @"8,d" NEWLINE
  118. @"9,a" TAB @"9,b" TAB @"9,c" TAB @"9,d" NEWLINE
  119. @"10,a" TAB @"10,b" TAB @"10,c" TAB @"10,d";
  120. NSArray *expected = @[@[@"1,a", @"1,b", @"1,c", @"1,\"d\""],
  121. @[@"2,a", @"2,b", @"2,c", @"2,d"],
  122. @[@"3,a", @"3,b", @"3,c", @"3,d"],
  123. @[@"4,a", @"4,b", @"4,c", @"4,d"],
  124. @[@"5,a", @"5,b", @"5,c", @"5,d"],
  125. @[@"6,a", @"6,b", @"6,c", @"6,d"],
  126. @[@"7,a", @"7,b", @"7,c", @"7,d"],
  127. @[@"8,a", @"8,b", @"8,c", @"8,d"],
  128. @[@"9,a", @"9,b", @"9,c", @"9,d"],
  129. @[@"10,a", @"10,b", @"10,c", @"10,d"]];
  130. NSArray *actual = [tsv componentsSeparatedByDelimiter:'\t'];
  131. TEST_ARRAYS(actual, expected);
  132. }
  133. - (void)testGithubIssue38 {
  134. NSString *csv = FIELD1 COMMA FIELD2 COMMA FIELD3 NEWLINE OCTOTHORPE;
  135. NSArray *expected = @[@[FIELD1, FIELD2, FIELD3]];
  136. TEST(csv, expected, CHCSVParserOptionsRecognizesComments);
  137. }
  138. - (void)testGithubIssue50 {
  139. NSString *csv = @"TRẦN,species_code,Scientific name,Author name,Common name,Family,Description,Habitat,\"Leaf size min (cm, 0 decimal digit)\",\"Leaf size max (cm, 0 decimal digit)\",Distribution,Current National Conservation Status,Growth requirements,Horticultural features,Uses,Associated fauna,Reference,species_id";
  140. NSArray *expected = @[@[@"TRẦN",@"species_code",@"Scientific name",@"Author name",@"Common name",@"Family",@"Description",@"Habitat",@"\"Leaf size min (cm, 0 decimal digit)\"",@"\"Leaf size max (cm, 0 decimal digit)\"",@"Distribution",@"Current National Conservation Status",@"Growth requirements",@"Horticultural features",@"Uses",@"Associated fauna",@"Reference",@"species_id"]];
  141. TEST(csv, expected);
  142. }
  143. - (void)testGithubIssue50Workaround {
  144. NSString *csv = @"TRẦN,species_code,Scientific name,Author name,Common name,Family,Description,Habitat,\"Leaf size min (cm, 0 decimal digit)\",\"Leaf size max (cm, 0 decimal digit)\",Distribution,Current National Conservation Status,Growth requirements,Horticultural features,Uses,Associated fauna,Reference,species_id";
  145. NSURL *url = [self temporaryURLForDelimitedString:csv];
  146. NSArray *actual = [NSArray arrayWithContentsOfCSVURL:url];
  147. NSArray *expected = @[@[@"TRẦN",@"species_code",@"Scientific name",@"Author name",@"Common name",@"Family",@"Description",@"Habitat",@"\"Leaf size min (cm, 0 decimal digit)\"",@"\"Leaf size max (cm, 0 decimal digit)\"",@"Distribution",@"Current National Conservation Status",@"Growth requirements",@"Horticultural features",@"Uses",@"Associated fauna",@"Reference",@"species_id"]];
  148. XCTAssertEqualObjects(actual, expected, @"failed");
  149. }
  150. - (void)testGithubIssue53 {
  151. NSString *csv = @"F1,F2,F3" NEWLINE @"a, \"b, B\",c" NEWLINE @"A,B,C" NEWLINE @"1,2,3" NEWLINE @"I,II,III";
  152. NSArray *expected = @[@[@"F1",@"F2",@"F3"], @[@"a", @" \"b, B\"", @"c"], @[@"A", @"B", @"C"], @[@"1", @"2", @"3"], @[@"I", @"II", @"III"]];
  153. TEST(csv, expected);
  154. }
  155. - (void)testGithubIssue64 {
  156. NSBundle *bundle = [NSBundle bundleForClass:[self class]];
  157. NSURL *fileURL = [bundle URLForResource:@"Issue64" withExtension:@"csv"];
  158. NSArray *actual = [NSArray arrayWithContentsOfCSVURL:fileURL];
  159. NSArray *expected = @[@[@"SplashID vID File -v2.0"],
  160. @[@"F"],
  161. @[@"T",@"21",@"Web Logins",@"Description",@"Username",@"Password",@"URL",@"Field 5",@"4",@""],
  162. @[@"F",@"21",@"test",@"me",@"23123123",@"www.ya.ru",@"",@"",@"4",@"",@"",@"",@"",@"",@"",@"Personal",@"\"aasdasd\r\radasdasd\""],
  163. @[@"T",@"3",@"Credit Cards",@"Description",@"Card #",@"Expiry Date",@"Name",@"PIN",@"18",@""],
  164. @[@"F",@"3",@"карта",@"123123123213",@"23/23",@"Лдлоло Лдлодло",@"23223",@"",@"18",@"",@"",@"",@"",@"",@"",@"Unfiled",@"\"фывфывыфв\r\r\rфывфыв\""],
  165. @[@"T",@"21",@"Web Logins",@"Description",@"Username",@"Password",@"URL",@"Field 5",@"4",@""],
  166. @[@"F",@"21",@"test 2",@"me",@"23123123",@"www.ya.ru",@"f5",@"f6",@"4",@"",@"",@"",@"",@"",@"",@"Personal",@"\"aasdasd\r\radasdasd\""],
  167. @[@"T",@"3",@"Credit Cards",@"Description",@"Card #",@"Expiry Date",@"Name",@"PIN",@"18",@""],
  168. @[@"F",@"3",@"карта 2",@"123123123213",@"23/23",@"Лдлоло Лдлодло",@"23223",@"",@"18",@"",@"",@"",@"",@"",@"",@"Unfiled",@"\"фывфывыфв\r\r\rфывфыв\""]];
  169. TEST_ARRAYS(actual, expected);
  170. }
  171. - (void)testGithubIssue65 {
  172. NSBundle *bundle = [NSBundle bundleForClass:[self class]];
  173. NSURL *fileURL = [bundle URLForResource:@"Issue65" withExtension:@"csv"];
  174. NSArray *actual = [NSArray arrayWithContentsOfCSVURL:fileURL];
  175. NSArray *expected = @[@[@"Bib", @"Name", @"Teamcode", @"Team"],
  176. @[@"71", @"DUMOULIN Tom", @"GIA", @"TEAM GIANT-SHIMANO"],
  177. @[@"41", @"CANCELLARA Fabian", @"TFR", @"TREK FACTORY RACING"],
  178. @[@"68", @"THOMAS Geraint", @"SKY", @"TEAM SKY"],
  179. @[@"37", @"QUINZIATO Manuel", @"BMC", @"BMC RACING TEAM"],
  180. @[@"46", @"SERGENT Jesse", @"TFR", @"TREK FACTORY RACING"],
  181. @[@"39", @"CUMMINGS Stephen", @"BMC", @"BMC RACING TEAM"],
  182. @[@"140", @"GRIVKO Andriy", @"AST", @"ASTANA PRO TEAM"],
  183. @[@"57", @"MOSER Moreno", @"CAN", @"CANNONDALE"],
  184. @[@"11", @"BOOM Lars", @"BEL", @"BELKIN-PRO CYCLING TEAM"],
  185. @[@"34", @"DENNIS Rohan", @"BMC", @"BMC RACING TEAM"],
  186. @[@"33", @"DILLIER Silvan", @"BMC", @"BMC RACING TEAM"],
  187. @[@"5", @"TERPSTRA Niki", @"OPQ", @"OMEGA PHARMA - QUICK-STEP CYCLING TEAM"],
  188. @[@"36", @"OSS Daniel", @"BMC", @"BMC RACING TEAM"],
  189. @[@"16", @"VAN EMDEN Jos", @"BEL", @"BELKIN-PRO CYCLING TEAM"],
  190. @[@"143", @"DOWSETT Alex", @"MOV", @"MOVISTAR TEAM"],
  191. @[@"104", @"HEPBURN Michael", @"OGE", @"ORICA GreenEDGE"],
  192. @[@"81", @"LANGEVELD Sebastian", @"GRS", @"GARMIN SHARP"],
  193. @[@"84", @"NAVARDAUSKAS Ramunas", @"GRS", @"GARMIN SHARP"],
  194. @[@"86", @"VAN BAARLE Dylan", @"GRS", @"GARMIN SHARP"],
  195. @[@"53", @"KOREN Kristijan", @"CAN", @"CANNONDALE"],
  196. @[@"127", @"SMUKULIS Gatis", @"KAT", @"TEAM KATUSHA"],
  197. @[@"1", @"STYBAR Zdenek", @"OPQ", @"OMEGA PHARMA - QUICK-STEP CYCLING TEAM"],
  198. @[@"31", @"GILBERT Philippe", @"BMC", @"BMC RACING TEAM"],
  199. @[@"184", @"LAMPAERT Yves", @"TSV", @"TOPSPORT VLAANDEREN - BALOISE"],
  200. @[@"44", @"HONDO Danilo", @"TFR", @"TREK FACTORY RACING"],
  201. @[@"88", @"MILLAR David", @"GRS", @"GARMIN SHARP"],
  202. @[@"106", @"KEUKELEIRE Jens", @"OGE", @"ORICA GreenEDGE"],
  203. @[@"61", @"BOASSON HAGEN Edvald", @"SKY", @"TEAM SKY"],
  204. @[@"38", @"VAN AVERMAET Greg", @"BMC", @"BMC RACING TEAM"],
  205. @[@"74", @"GESCHKE Simon", @"GIA", @"TEAM GIANT-SHIMANO"],
  206. @[@"125", @"PORSEV Alexandr", @"KAT", @"TEAM KATUSHA"],
  207. @[@"64", @"KNEES Christian", @"SKY", @"TEAM SKY"],
  208. @[@"17", @"VANMARCKE Sep", @"BEL", @"BELKIN-PRO CYCLING TEAM"],
  209. @[@"124", @"KUZNETSOV Viacheslav", @"KAT", @"TEAM KATUSHA"],
  210. @[@"82", @"BAUER Jack", @"GRS", @"GARMIN SHARP"],
  211. @[@"8", @"VERMOTE Julien", @"OPQ", @"OMEGA PHARMA - QUICK-STEP CYCLING TEAM"],
  212. @[@"7", @"VAN KEIRSBULCK Guillaume", @"OPQ", @"OMEGA PHARMA - QUICK-STEP CYCLING TEAM"],
  213. @[@"43", @"DEVOLDER Stijn", @"TFR", @"TREK FACTORY RACING"],
  214. @[@"28", @"WELLENS Tim", @"LTB", @"LOTTO BELISOL"],
  215. @[@"121", @"BRUTT Pavel", @"KAT", @"TEAM KATUSHA"],
  216. @[@"107", @"MOURIS Jens", @"OGE", @"ORICA GreenEDGE"],
  217. @[@"161", @"APPOLLONIO Davide", @"ALM", @"AG2R LA MONDIALE"],
  218. @[@"145", @"VENTOSO ALBERDI Francisco Jose", @"MOV", @"MOVISTAR TEAM"],
  219. @[@"148", @"SÜTTERLIN Jasha", @"MOV", @"MOVISTAR TEAM"],
  220. @[@"75", @"JANSE VAN RENSBURG Reinardt", @"GIA", @"TEAM GIANT-SHIMANO"],
  221. @[@"21", @"GREIPEL André", @"LTB", @"LOTTO BELISOL"],
  222. @[@"186", @"VAN HOECKE Gijs", @"TSV", @"TOPSPORT VLAANDEREN - BALOISE"],
  223. @[@"116", @"ROUX Anthony", @"FDJ", @"FDJ.fr"],
  224. @[@"141", @"GUTIERREZ PALACIOS José Ivan", @"MOV", @"MOVISTAR TEAM"],
  225. @[@"96", @"ROVNI Ivan", @"TCS", @"TINKOFF-SAXO"],
  226. @[@"23", @"BROECKX Stig", @"LTB", @"LOTTO BELISOL"],
  227. @[@"166", @"GOUGEARD Alexis", @"ALM", @"AG2R LA MONDIALE"],
  228. @[@"122", @"IGNATYEV Mikhail", @"KAT", @"TEAM KATUSHA"],
  229. @[@"112", @"BOUCHER David", @"FDJ", @"FDJ.fr"],
  230. @[@"109", @"HOWARD Leigh", @"OGE", @"ORICA GreenEDGE"],
  231. @[@"65", @"ROWE Luke", @"SKY", @"TEAM SKY"],
  232. @[@"48", @"VAN POPPEL Danny", @"TFR", @"TREK FACTORY RACING"],
  233. @[@"15", @"TANKINK Bram", @"BEL", @"BELKIN-PRO CYCLING TEAM"],
  234. @[@"24", @"ROELANDTS Jurgen", @"LTB", @"LOTTO BELISOL"],
  235. @[@"178", @"NAULEAU Bryan", @"EUC", @"TEAM EUROPCAR"],
  236. @[@"4", @"STEEGMANS Gert", @"OPQ", @"OMEGA PHARMA - QUICK-STEP CYCLING TEAM"],
  237. @[@"69", @"PUCCIO Salvatore", @"SKY", @"TEAM SKY"],
  238. @[@"85", @"NUYENS Nick", @"GRS", @"GARMIN SHARP"],
  239. @[@"199", @"DE TROYER Tim", @"WGG", @"WANTY - GROUPE GOBERT"],
  240. @[@"128", @"TCATEVICH Alexsei", @"KAT", @"TEAM KATUSHA"],
  241. @[@"25", @"SIEBERG Marcel", @"LTB", @"LOTTO BELISOL"],
  242. @[@"6", @"TRENTIN Matteo", @"OPQ", @"OMEGA PHARMA - QUICK-STEP CYCLING TEAM"],
  243. @[@"154", @"CIMOLAI Davide", @"LAM", @"LAMPRE-MERIDA"],
  244. @[@"18", @"WYNANTS Maarten", @"BEL", @"BELKIN-PRO CYCLING TEAM"],
  245. @[@"2", @"BOONEN Tom", @"OPQ", @"OMEGA PHARMA - QUICK-STEP CYCLING TEAM"],
  246. @[@"188", @"WAEYTENS Zico", @"TSV", @"TOPSPORT VLAANDEREN - BALOISE"],
  247. @[@"198", @"DRUCKER Jean-Pierre", @"WGG", @"WANTY - GROUPE GOBERT"],
  248. @[@"55", @"MARCATO Marco", @"CAN", @"CANNONDALE"],
  249. @[@"153", @"POZZATO Filippo", @"LAM", @"LAMPRE-MERIDA"],
  250. @[@"94", @"MCCARTHY Jay", @"TCS", @"TINKOFF-SAXO"],
  251. @[@"87", @"HAAS Nathan", @"GRS", @"GARMIN SHARP"],
  252. @[@"123", @"KOCHETKOV Pavel", @"KAT", @"TEAM KATUSHA"],
  253. @[@"83", @"FARRAR Tyler", @"GRS", @"GARMIN SHARP"],
  254. @[@"114", @"OFFREDO Yoann", @"FDJ", @"FDJ.fr"],
  255. @[@"95", @"PETROV Evgeny", @"TCS", @"TINKOFF-SAXO"],
  256. @[@"3", @"KEISSE Iljo", @"OPQ", @"OMEGA PHARMA - QUICK-STEP CYCLING TEAM"],
  257. @[@"105", @"HOWSON Damien", @"OGE", @"ORICA GreenEDGE"],
  258. @[@"52", @"BETTIOL Alberto", @"CAN", @"CANNONDALE"],
  259. @[@"157", @"RICHEZE Maximiliano Ariel", @"LAM", @"LAMPRE-MERIDA"],
  260. @[@"196", @"SELVAGGI Mirko", @"WGG", @"WANTY - GROUPE GOBERT"],
  261. @[@"164", @"GASTAUER Ben", @"ALM", @"AG2R LA MONDIALE"],
  262. @[@"117", @"SOUPE Geoffrey", @"FDJ", @"FDJ.fr"],
  263. @[@"47", @"VAN POPPEL Boy", @"TFR", @"TREK FACTORY RACING"],
  264. @[@"66", @"STANNARD Ian", @"SKY", @"TEAM SKY"],
  265. @[@"192", @"VEUCHELEN Frederik", @"WGG", @"WANTY - GROUPE GOBERT"],
  266. @[@"160", @"POLANC Jan", @"LAM", @"LAMPRE-MERIDA"],
  267. @[@"162", @"BAGDONAS Gediminas", @"ALM", @"AG2R LA MONDIALE"],
  268. @[@"195", @"DE VREESE Laurens", @"WGG", @"WANTY - GROUPE GOBERT"],
  269. @[@"26", @"VANENDERT Jelle", @"LTB", @"LOTTO BELISOL"],
  270. @[@"92", @"KROON Karsten", @"TCS", @"TINKOFF-SAXO"],
  271. @[@"183", @"STEELS Stijn", @"TSV", @"TOPSPORT VLAANDEREN - BALOISE"],
  272. @[@"98", @"TRUSOV Nikolay", @"TCS", @"TINKOFF-SAXO"],
  273. @[@"131", @"BOZIC Borut", @"AST", @"ASTANA PRO TEAM"],
  274. @[@"179", @"GENE Yohann", @"EUC", @"TEAM EUROPCAR"],
  275. @[@"22", @"DEBUSSCHERE Jens", @"LTB", @"LOTTO BELISOL"],
  276. @[@"146", @"ROJAS GIL Jose Joaquin", @"MOV", @"MOVISTAR TEAM"],
  277. @[@"118", @"VAUGRENARD Benoît", @"FDJ", @"FDJ.fr"],
  278. @[@"156", @"MORI Manuele", @"LAM", @"LAMPRE-MERIDA"],
  279. @[@"45", @"NIZZOLO Giacomo", @"TFR", @"TREK FACTORY RACING"],
  280. @[@"63", @"EARLE Nathan", @"SKY", @"TEAM SKY"],
  281. @[@"152", @"BONIFAZIO Niccolo", @"LAM", @"LAMPRE-MERIDA"],
  282. @[@"78", @"VEELERS Tom", @"GIA", @"TEAM GIANT-SHIMANO"],
  283. @[@"138", @"TLEUBAYEV Ruslan", @"AST", @"ASTANA PRO TEAM"],
  284. @[@"54", @"LONGO BORGHINI Paolo", @"CAN", @"CANNONDALE"],
  285. @[@"194", @"JANS Roy", @"WGG", @"WANTY - GROUPE GOBERT"],
  286. @[@"175", @"JEROME Vincent", @"EUC", @"TEAM EUROPCAR"],
  287. @[@"77", @"STAMSNIJDER Tom", @"GIA", @"TEAM GIANT-SHIMANO"],
  288. @[@"111", @"BOUHANNI Nacer", @"FDJ", @"FDJ.fr"],
  289. @[@"76", @"MEZGEC Luka", @"GIA", @"TEAM GIANT-SHIMANO"],
  290. @[@"72", @"BULGAC Brian", @"GIA", @"TEAM GIANT-SHIMANO"],
  291. @[@"58", @"SABATINI Fabio", @"CAN", @"CANNONDALE"],
  292. @[@"177", @"MARTINEZ Yannick", @"EUC", @"TEAM EUROPCAR"],
  293. @[@"102", @"GOSS Matthew Harley", @"OGE", @"ORICA GreenEDGE"],
  294. @[@"103", @"HAYMAN Mathew", @"OGE", @"ORICA GreenEDGE"],
  295. @[@"67", @"SUTTON Christopher", @"SKY", @"TEAM SKY"],
  296. @[@"197", @"VAN MELSEN Kevin", @"WGG", @"WANTY - GROUPE GOBERT"],
  297. @[@"165", @"GRETSCH Patrick", @"ALM", @"AG2R LA MONDIALE"],
  298. @[@"176", @"LAMOISSON Morgan", @"EUC", @"TEAM EUROPCAR"],
  299. @[@"91", @"BRESCHEL Matti", @"TCS", @"TINKOFF-SAXO"],
  300. @[@"14", @"MOLLEMA Bauke", @"BEL", @"BELKIN-PRO CYCLING TEAM"],
  301. @[@"113", @"JEANNESSON Arnold", @"FDJ", @"FDJ.fr"],
  302. @[@"155", @"FAVILLI Elia", @"LAM", @"LAMPRE-MERIDA"],
  303. @[@"187", @"VAN BILSEN Kenneth", @"TSV", @"TOPSPORT VLAANDEREN - BALOISE"],
  304. @[@"185", @"SPRENGERS Thomas", @"TSV", @"TOPSPORT VLAANDEREN - BALOISE"],
  305. @[@"180", @"PICHOT Alexandre", @"EUC", @"TEAM EUROPCAR"],
  306. @[@"182", @"DECLERCQ Tim", @"TSV", @"TOPSPORT VLAANDEREN - BALOISE"],
  307. @[@"12", @"LEEZER Thomas", @"BEL", @"BELKIN-PRO CYCLING TEAM"],
  308. @[@"136", @"HUFFMAN Evan", @"AST", @"ASTANA PRO TEAM"],
  309. @[@"110", @"KRUOPIS Aidis", @"OGE", @"ORICA GreenEDGE"],
  310. @[@"93", @"KOLÁR Michal", @"TCS", @"TINKOFF-SAXO"],
  311. @[@"32", @"BURGHARDT Marcus", @"BMC", @"BMC RACING TEAM"],
  312. @[@"42", @"ALAFACI Eugenio", @"TFR", @"TREK FACTORY RACING"],
  313. @[@"56", @"MARINO Jean Marc", @"CAN", @"CANNONDALE"],
  314. @[@"73", @"CURVERS Roy", @"GIA", @"TEAM GIANT-SHIMANO"],
  315. @[@"137", @"IGLINSKIY Valentin", @"AST", @"ASTANA PRO TEAM"],
  316. @[@"13", @"MARKUS Barry", @"BEL", @"BELKIN-PRO CYCLING TEAM"],
  317. @[@"174", @"HUREL Tony", @"EUC", @"TEAM EUROPCAR"],
  318. @[@"142", @"QUINTANA Dayer", @"MOV", @"MOVISTAR TEAM"],
  319. @[@"134", @"GUARDINI Andrea", @"AST", @"ASTANA PRO TEAM"],
  320. @[@"168", @"KERN Julian", @"ALM", @"AG2R LA MONDIALE"],
  321. @[@"147", @"SANZ Enrique", @"MOV", @"MOVISTAR TEAM"],
  322. @[@"115", @"PICHON Laurent", @"FDJ", @"FDJ.fr"],
  323. @[@"132", @"DYACHENKO Alexandr", @"AST", @"ASTANA PRO TEAM"],
  324. @[@"163", @"DANIEL Maxime", @"ALM", @"AG2R LA MONDIALE"],
  325. @[@"169", @"CHAINEL Steve", @"ALM", @"AG2R LA MONDIALE"],
  326. @[@"144", @"LASTRAS GARCIA Pablo", @"MOV", @"MOVISTAR TEAM"],
  327. @[@"133", @"KAMYSHEV Arman", @"AST", @"ASTANA PRO TEAM"],
  328. @[@"181", @"VAN STAEYEN Michael", @"TSV", @"TOPSPORT VLAANDEREN - BALOISE"],
  329. @[@"29", @"DOCKX Gert", @"LTB", @"LOTTO BELISOL"],
  330. @[@"173", @"DUCHESNE Antoine", @"EUC", @"TEAM EUROPCAR"]];
  331. TEST_ARRAYS(actual, expected);
  332. }
  333. - (void)testGithubIssue79 {
  334. NSString *scsv = @"16681;6;Orehovyj boulevard, ul. Musy Dzhalilja (odd side);20;out;55.6141571054;37.7460757208;800;34;34;0;0;0;0;0;1";
  335. NSArray *parsed = [scsv componentsSeparatedByDelimiter:';'];
  336. NSArray *expected = @[@[@"16681",@"6",@"Orehovyj boulevard, ul. Musy Dzhalilja (odd side)",@"20",@"out",@"55.6141571054",@"37.7460757208",@"800",@"34",@"34",@"0",@"0",@"0",@"0",@"0",@"1"]];
  337. TEST_ARRAYS(parsed, expected);
  338. NSURL *url = [self temporaryURLForDelimitedString:scsv];
  339. parsed = [NSArray arrayWithContentsOfDelimitedURL:url delimiter:';'];
  340. TEST_ARRAYS(parsed, expected);
  341. // Rather than embedding the entire contents of this file within the source here,
  342. // I'm going to assume that if there are the correct number of records and
  343. // the correct number of fields per record, then it probably parsed correctly.
  344. NSBundle *bundle = [NSBundle bundleForClass:[self class]];
  345. NSURL *fileURL = [bundle URLForResource:@"Issue79" withExtension:@"csv"];
  346. NSArray *contents = [NSArray arrayWithContentsOfDelimitedURL:fileURL delimiter:';'];
  347. XCTAssertEqual(contents.count, 1112, @"Unexpected number of lines: %ld", contents.count);
  348. [contents enumerateObjectsUsingBlock:^(NSArray *line, NSUInteger idx, BOOL *stop) {
  349. XCTAssertEqual(line.count, 14, @"Unexpected number of lines on record %ld: %ld", idx, line.count);
  350. }];
  351. // try loading the file as an array of ordered dictionaries
  352. contents = [NSArray arrayWithContentsOfDelimitedURL:fileURL options:CHCSVParserOptionsUsesFirstLineAsKeys delimiter:';'];
  353. XCTAssertEqual(contents.count, 1111, @"Unexpected number of lines: %ld", contents.count);
  354. NSArray *keys = @[@"id_entrance",@"name",@"id_station",@"direction",@"lat",@"lon",@"max_width",@"min_step",@"min_step_ramp",@"lift",@"lift_minus_step",@"min_rail_width",@"max_rail_width",@"max_angle"];
  355. [contents enumerateObjectsUsingBlock:^(CHCSVOrderedDictionary *record, NSUInteger idx, BOOL *stop) {
  356. XCTAssertEqual(record.count, 14, @"Unexpected number of lines on record %ld: %ld", idx, record.count);
  357. XCTAssertEqualObjects(record.allKeys, keys, @"Unexpected record keys: %@", record.allKeys);
  358. }];
  359. }
  360. - (void)testEmptyRecords {
  361. NSString *csv = NEWLINE FIELD1 NEWLINE FIELD1 NEWLINE NEWLINE FIELD1 NEWLINE NEWLINE FIELD1 NEWLINE UTF8FIELD4;
  362. NSArray *expected = @[@[EMPTY], @[FIELD1], @[FIELD1], @[EMPTY], @[FIELD1], @[EMPTY], @[FIELD1], @[UTF8FIELD4]];
  363. TEST(csv, expected);
  364. }
  365. - (void)testEmptyFields {
  366. NSString *csv = COMMA COMMA;
  367. NSArray *expected = @[@[EMPTY, EMPTY, EMPTY]];
  368. TEST(csv, expected);
  369. }
  370. - (void)testSimpleWithInnerQuote {
  371. NSString *csv = FIELD1 COMMA FIELD2 DOUBLEQUOTE FIELD3;
  372. NSArray *expected = @[@[FIELD1, FIELD2 DOUBLEQUOTE FIELD3]];
  373. TEST(csv, expected);
  374. }
  375. - (void)testSimpleWithDoubledInnerQuote {
  376. NSString *csv = FIELD1 COMMA FIELD2 DOUBLEQUOTE DOUBLEQUOTE FIELD3;
  377. NSArray *expected = @[@[FIELD1, FIELD2 DOUBLEQUOTE DOUBLEQUOTE FIELD3]];
  378. TEST(csv, expected);
  379. }
  380. - (void)testInterspersedDoubleQuotes {
  381. NSString *csv = FIELD1 COMMA FIELD2 DOUBLEQUOTE FIELD3 DOUBLEQUOTE;
  382. NSArray *expected = @[@[FIELD1, FIELD2 DOUBLEQUOTE FIELD3 DOUBLEQUOTE]];
  383. TEST(csv, expected);
  384. }
  385. - (void)testSimpleQuoted {
  386. NSString *csv = QUOTED_FIELD1 COMMA QUOTED_FIELD2 COMMA QUOTED_FIELD3;
  387. NSArray *expected = @[@[QUOTED_FIELD1, QUOTED_FIELD2, QUOTED_FIELD3]];
  388. TEST(csv, expected);
  389. }
  390. - (void)testSimpleQuotedSanitized {
  391. NSString *csv = QUOTED_FIELD1 COMMA QUOTED_FIELD2 COMMA QUOTED_FIELD3;
  392. NSArray *expected = @[@[FIELD1, FIELD2, FIELD3]];
  393. TEST(csv, expected, CHCSVParserOptionsSanitizesFields);
  394. }
  395. - (void)testSimpleMultiline {
  396. NSString *csv = FIELD1 COMMA FIELD2 COMMA FIELD3 NEWLINE FIELD1 COMMA FIELD2 COMMA FIELD3;
  397. NSArray *expected = @[@[FIELD1, FIELD2, FIELD3], @[FIELD1, FIELD2, FIELD3]];
  398. TEST(csv, expected);
  399. }
  400. - (void)testQuotedDelimiter {
  401. NSString *csv = FIELD1 COMMA DOUBLEQUOTE FIELD2 COMMA FIELD3 DOUBLEQUOTE;
  402. NSArray *expected = @[@[FIELD1, DOUBLEQUOTE FIELD2 COMMA FIELD3 DOUBLEQUOTE]];
  403. TEST(csv, expected);
  404. }
  405. - (void)testSanitizedQuotedDelimiter {
  406. NSString *csv = FIELD1 COMMA DOUBLEQUOTE FIELD2 COMMA FIELD3 DOUBLEQUOTE;
  407. NSArray *expected = @[@[FIELD1, FIELD2 COMMA FIELD3]];
  408. TEST(csv, expected, CHCSVParserOptionsSanitizesFields);
  409. }
  410. - (void)testQuotedMultiline {
  411. NSString *csv = FIELD1 COMMA DOUBLEQUOTE MULTILINE_FIELD DOUBLEQUOTE NEWLINE FIELD2;
  412. NSArray *expected = @[@[FIELD1, DOUBLEQUOTE MULTILINE_FIELD DOUBLEQUOTE], @[FIELD2]];
  413. TEST(csv, expected);
  414. }
  415. - (void)testSanitizedMultiline {
  416. NSString *csv = FIELD1 COMMA DOUBLEQUOTE MULTILINE_FIELD DOUBLEQUOTE NEWLINE FIELD2;
  417. NSArray *expected = @[@[FIELD1, MULTILINE_FIELD], @[FIELD2]];
  418. TEST(csv, expected, CHCSVParserOptionsSanitizesFields);
  419. }
  420. - (void)testWhitespace {
  421. NSString *csv = FIELD1 COMMA SPACE SPACE SPACE FIELD2 COMMA FIELD3 SPACE SPACE SPACE;
  422. NSArray *expected = @[@[FIELD1, SPACE SPACE SPACE FIELD2, FIELD3 SPACE SPACE SPACE]];
  423. TEST(csv, expected);
  424. }
  425. - (void)testTrimmedWhitespace {
  426. NSString *csv = FIELD1 COMMA SPACE SPACE SPACE FIELD2 COMMA FIELD3 SPACE SPACE SPACE;
  427. NSArray *expected = @[@[FIELD1, FIELD2, FIELD3]];
  428. TEST(csv, expected, CHCSVParserOptionsTrimsWhitespace);
  429. }
  430. - (void)testSanitizedQuotedWhitespace {
  431. NSString *csv = FIELD1 COMMA DOUBLEQUOTE SPACE SPACE SPACE FIELD2 DOUBLEQUOTE COMMA DOUBLEQUOTE FIELD3 SPACE SPACE SPACE DOUBLEQUOTE;
  432. NSArray *expected = @[@[FIELD1, SPACE SPACE SPACE FIELD2, FIELD3 SPACE SPACE SPACE]];
  433. TEST(csv, expected, CHCSVParserOptionsSanitizesFields);
  434. }
  435. - (void)testUnrecognizedComment {
  436. NSString *csv = FIELD1 NEWLINE OCTOTHORPE FIELD2;
  437. NSArray *expected = @[@[FIELD1], @[OCTOTHORPE FIELD2]];
  438. TEST(csv, expected);
  439. }
  440. - (void)testRecognizedComment {
  441. NSString *csv = FIELD1 NEWLINE OCTOTHORPE FIELD2;
  442. NSArray *expected = @[@[FIELD1]];
  443. TEST(csv, expected, CHCSVParserOptionsRecognizesComments);
  444. }
  445. - (void)testTrailingNewline {
  446. NSString *csv = FIELD1 COMMA FIELD2 NEWLINE;
  447. NSArray *expected = @[@[FIELD1, FIELD2]];
  448. TEST(csv, expected);
  449. }
  450. - (void)testTrailingSpace {
  451. NSString *csv = FIELD1 COMMA FIELD2 NEWLINE SPACE;
  452. NSArray *expected = @[@[FIELD1, FIELD2], @[SPACE]];
  453. TEST(csv, expected);
  454. }
  455. - (void)testTrailingTrimmedSpace {
  456. NSString *csv = FIELD1 COMMA FIELD2 NEWLINE SPACE;
  457. NSArray *expected = @[@[FIELD1, FIELD2], @[EMPTY]];
  458. TEST(csv, expected, CHCSVParserOptionsTrimsWhitespace);
  459. }
  460. - (void)testEmoji {
  461. NSString *csv = @"1️⃣,2️⃣,3️⃣,4️⃣,5️⃣" NEWLINE @"6️⃣,7️⃣,8️⃣,9️⃣,0️⃣";
  462. NSArray *expected = @[@[@"1️⃣",@"2️⃣",@"3️⃣",@"4️⃣",@"5️⃣"],@[@"6️⃣",@"7️⃣",@"8️⃣",@"9️⃣",@"0️⃣"]];
  463. TEST(csv, expected);
  464. }
  465. #pragma mark - Testing Backslashes
  466. - (void)testUnrecognizedBackslash {
  467. NSString *csv = FIELD1 COMMA FIELD2 BACKSLASH COMMA FIELD3;
  468. NSArray *expected = @[@[FIELD1, FIELD2 BACKSLASH, FIELD3]];
  469. TEST(csv, expected);
  470. }
  471. - (void)testBackslashEscapedComma {
  472. NSString *csv = FIELD1 COMMA FIELD2 BACKSLASH COMMA FIELD3;
  473. NSArray *expected = @[@[FIELD1, FIELD2 BACKSLASH COMMA FIELD3]];
  474. TEST(csv, expected, CHCSVParserOptionsRecognizesBackslashesAsEscapes);
  475. }
  476. - (void)testSantizedBackslashEscapedComma {
  477. NSString *csv = FIELD1 COMMA FIELD2 BACKSLASH COMMA FIELD3;
  478. NSArray *expected = @[@[FIELD1, FIELD2 COMMA FIELD3]];
  479. TEST(csv, expected, CHCSVParserOptionsRecognizesBackslashesAsEscapes | CHCSVParserOptionsSanitizesFields);
  480. }
  481. - (void)testBackslashEscapedNewline {
  482. NSString *csv = FIELD1 COMMA FIELD2 BACKSLASH NEWLINE FIELD3;
  483. NSArray *expected = @[@[FIELD1, FIELD2 BACKSLASH NEWLINE FIELD3]];
  484. TEST(csv, expected, CHCSVParserOptionsRecognizesBackslashesAsEscapes);
  485. }
  486. - (void)testSantizedBackslashEscapedNewline {
  487. NSString *csv = FIELD1 COMMA FIELD2 BACKSLASH NEWLINE FIELD3;
  488. NSArray *expected = @[@[FIELD1, FIELD2 NEWLINE FIELD3]];
  489. TEST(csv, expected, CHCSVParserOptionsRecognizesBackslashesAsEscapes | CHCSVParserOptionsSanitizesFields);
  490. }
  491. #pragma mark - Testing First Line as Keys
  492. - (void)testOrderedDictionary {
  493. CHCSVOrderedDictionary *dictionary = [CHCSVOrderedDictionary dictionaryWithObjects:@[FIELD1, FIELD2, FIELD3] forKeys:@[FIELD1, FIELD2, FIELD3]];
  494. NSArray *expected = @[FIELD1, FIELD2, FIELD3];
  495. XCTAssertEqualObjects(dictionary.allKeys, expected, @"Unexpected field order");
  496. XCTAssertEqualObjects(dictionary[0], FIELD1, @"Unexpected field");
  497. XCTAssertEqualObjects(dictionary[1], FIELD2, @"Unexpected field");
  498. XCTAssertEqualObjects(dictionary[2], FIELD3, @"Unexpected field");
  499. XCTAssertEqualObjects(dictionary[FIELD1], FIELD1, @"Unexpected field");
  500. XCTAssertEqualObjects(dictionary[FIELD2], FIELD2, @"Unexpected field");
  501. XCTAssertEqualObjects(dictionary[FIELD3], FIELD3, @"Unexpected field");
  502. NSDictionary *regularDictionary = @{FIELD1 : FIELD1, FIELD2 : FIELD2, FIELD3 : FIELD3 };
  503. XCTAssertNotEqualObjects(regularDictionary, expected, @"Somehow equal??");
  504. }
  505. - (void)testFirstLineAsKeys {
  506. NSString *csv = FIELD1 COMMA FIELD2 COMMA FIELD3 NEWLINE FIELD1 COMMA FIELD2 COMMA FIELD3;
  507. NSArray *expected = @[
  508. [CHCSVOrderedDictionary dictionaryWithObjects:@[FIELD1, FIELD2, FIELD3] forKeys:@[FIELD1, FIELD2, FIELD3]]
  509. ];
  510. TEST(csv, expected, CHCSVParserOptionsUsesFirstLineAsKeys);
  511. }
  512. - (void)testFirstLineAsKeys_SingleLine {
  513. NSString *csv = FIELD1 COMMA FIELD2 COMMA FIELD3 NEWLINE;
  514. NSArray *expected = @[];
  515. TEST(csv, expected, CHCSVParserOptionsUsesFirstLineAsKeys);
  516. csv = FIELD1 COMMA FIELD2 COMMA FIELD3;
  517. TEST(csv, expected, CHCSVParserOptionsUsesFirstLineAsKeys);
  518. }
  519. - (void)testFirstLineAsKeys_MismatchedFieldCount {
  520. NSString *csv = FIELD1 COMMA FIELD2 COMMA FIELD3 NEWLINE FIELD1 COMMA FIELD2 COMMA FIELD3 COMMA FIELD1;
  521. NSError *error = nil;
  522. (void)[csv componentsSeparatedByDelimiter:[COMMA characterAtIndex:0] options:CHCSVParserOptionsUsesFirstLineAsKeys error:&error];
  523. XCTAssertNotNil(error, @"Expected error");
  524. XCTAssertEqualObjects(error.domain, CHCSVErrorDomain, @"Unexpected error");
  525. XCTAssertEqual(error.code, CHCSVErrorCodeIncorrectNumberOfFields, @"Unexpected error");
  526. }
  527. #pragma mark - Testing Valid Delimiters
  528. - (void)testAllowedDelimiter_Octothorpe {
  529. NSString *csv = FIELD1 OCTOTHORPE FIELD2 OCTOTHORPE FIELD3;
  530. NSArray *actual = [csv componentsSeparatedByDelimiter:'#'];
  531. NSArray *expected = @[@[FIELD1, FIELD2, FIELD3]];
  532. TEST_ARRAYS(actual, expected);
  533. }
  534. - (void)testDisallowedDelimiter_Octothorpe {
  535. NSString *csv = FIELD1 OCTOTHORPE FIELD2 OCTOTHORPE FIELD3;
  536. XCTAssertThrows([csv componentsSeparatedByDelimiter:'#' options:CHCSVParserOptionsRecognizesComments], @"failed");
  537. }
  538. - (void)testAllowedDelimiter_Backslash {
  539. NSString *csv = FIELD1 BACKSLASH FIELD2 BACKSLASH FIELD3;
  540. NSArray *actual = [csv componentsSeparatedByDelimiter:'\\'];
  541. NSArray *expected = @[@[FIELD1, FIELD2, FIELD3]];
  542. TEST_ARRAYS(actual, expected);
  543. }
  544. - (void)testDisallowedDelimiter_Backslash {
  545. NSString *csv = FIELD1 BACKSLASH FIELD2 BACKSLASH FIELD3;
  546. XCTAssertThrows([csv componentsSeparatedByDelimiter:'\\' options:CHCSVParserOptionsRecognizesBackslashesAsEscapes], @"failed");
  547. }
  548. - (void)testAllowedDelimiter_Equal {
  549. NSString *csv = FIELD1 EQUAL FIELD2 EQUAL FIELD3;
  550. NSArray *actual = [csv componentsSeparatedByDelimiter:'='];
  551. NSArray *expected = @[@[FIELD1, FIELD2, FIELD3]];
  552. TEST_ARRAYS(actual, expected);
  553. }
  554. - (void)testDisallowedDelimiter_Equal {
  555. NSString *csv = FIELD1 EQUAL FIELD2 EQUAL FIELD3;
  556. XCTAssertThrows([csv componentsSeparatedByDelimiter:'=' options:CHCSVParserOptionsRecognizesLeadingEqualSign], @"failed");
  557. }
  558. #pragma mark - Testing Leading Equal
  559. - (void)testLeadingEqual {
  560. NSString *csv = FIELD1 COMMA EQUAL QUOTED_FIELD2 COMMA EQUAL QUOTED_FIELD3;
  561. NSArray *expected = @[@[FIELD1, EQUAL QUOTED_FIELD2, EQUAL QUOTED_FIELD3]];
  562. TEST(csv, expected, CHCSVParserOptionsRecognizesLeadingEqualSign);
  563. }
  564. - (void)testSanitizedLeadingEqual {
  565. NSString *csv = FIELD1 COMMA EQUAL QUOTED_FIELD2 COMMA EQUAL QUOTED_FIELD3;
  566. NSArray *expected = @[@[FIELD1, FIELD2, FIELD3]];
  567. TEST(csv, expected, CHCSVParserOptionsRecognizesLeadingEqualSign | CHCSVParserOptionsSanitizesFields);
  568. }
  569. @end