// Copyright 2009-2022 Josh Close // This file is a part of CsvHelper and is dual licensed under MS-PL and Apache 2.0. // See LICENSE.txt for details or visit http://www.opensource.org/licenses/ms-pl.html for MS-PL and http://opensource.org/licenses/Apache-2.0 for Apache 2.0. // https://github.com/JoshClose/CsvHelper using System; using System.Collections.Generic; using System.Diagnostics; using System.Globalization; using System.IO; using System.Linq; using System.Text.RegularExpressions; using CsvHelper.Configuration; using CsvHelper.Tests.Mocks; using CsvHelper.TypeConversion; using Xunit; #pragma warning disable 649 namespace CsvHelper.Tests { public class CsvReaderTests { [Fact] public void HasHeaderRecordNotReadExceptionTest() { var parserMock = new ParserMock(); var reader = new CsvReader(parserMock); Assert.Throws(() => reader.GetField(0)); } [Fact] public void HasHeaderRecordTest() { var parserMock = new ParserMock { { "One", "Two" }, { "1", "2" }, }; var reader = new CsvReader(parserMock); reader.Read(); reader.ReadHeader(); reader.Read(); // Check to see if the header record and first record are set properly. Assert.Equal(Convert.ToInt32("1"), reader.GetField("One")); Assert.Equal(Convert.ToInt32("2"), reader.GetField("Two")); Assert.Equal(Convert.ToInt32("1"), reader.GetField(0)); Assert.Equal(Convert.ToInt32("2"), reader.GetField(1)); } [Fact] public void GetTypeTest() { var data = new[] { "1", "blah", DateTime.Now.ToString("O"), "true", "c", "", Guid.NewGuid().ToString(), }; var parserMock = new ParserMock(); parserMock.Add(data); parserMock.Add(data); parserMock.Add(null); var reader = new CsvReader(parserMock); reader.Read(); Assert.Equal(Convert.ToInt16(data[0]), reader.GetField(0)); Assert.Equal(Convert.ToInt16(data[0]), reader.GetField(0)); Assert.Null(reader.GetField(5)); Assert.Equal(Convert.ToInt32(data[0]), reader.GetField(0)); Assert.Equal(Convert.ToInt32(data[0]), reader.GetField(0)); Assert.Null(reader.GetField(5)); Assert.Equal(Convert.ToInt64(data[0]), reader.GetField(0)); Assert.Equal(Convert.ToInt64(data[0]), reader.GetField(0)); Assert.Null(reader.GetField(5)); Assert.Equal(Convert.ToDecimal(data[0]), reader.GetField(0)); Assert.Equal(Convert.ToDecimal(data[0]), reader.GetField(0)); Assert.Null(reader.GetField(5)); Assert.Equal(Convert.ToSingle(data[0]), reader.GetField(0)); Assert.Equal(Convert.ToSingle(data[0]), reader.GetField(0)); Assert.Null(reader.GetField(5)); Assert.Equal(Convert.ToDouble(data[0]), reader.GetField(0)); Assert.Equal(Convert.ToDouble(data[0]), reader.GetField(0)); Assert.Null(reader.GetField(5)); Assert.Equal(data[1], reader.GetField(1)); Assert.Equal(string.Empty, reader.GetField(5)); Assert.Equal(Convert.ToDateTime(data[2]), reader.GetField(2)); Assert.Equal(Convert.ToDateTime(data[2]), reader.GetField(2)); Assert.Null(reader.GetField(5)); Assert.Equal(Convert.ToBoolean(data[3]), reader.GetField(3)); Assert.Equal(Convert.ToBoolean(data[3]), reader.GetField(3)); Assert.Null(reader.GetField(5)); Assert.Equal(Convert.ToChar(data[4]), reader.GetField(4)); Assert.Equal(Convert.ToChar(data[4]), reader.GetField(4)); Assert.Null(reader.GetField(5)); Assert.Equal(new Guid(data[6]), reader.GetField(6)); Assert.Null(reader.GetField(5)); } [Fact] public void GetFieldByIndexTest() { var config = new CsvConfiguration(CultureInfo.InvariantCulture) { HasHeaderRecord = false, }; var parserMock = new ParserMock(config) { { "1", "2" }, }; var reader = new CsvReader(parserMock); reader.Read(); Assert.Equal(1, reader.GetField(0)); Assert.Equal(2, reader.GetField(1)); } [Fact] public void GetFieldByNameTest() { var data1 = new[] { "One", "Two" }; var data2 = new[] { "1", "2" }; var parserMock = new ParserMock(); parserMock.Add(data1); parserMock.Add(data2); var reader = new CsvReader(parserMock); reader.Read(); reader.ReadHeader(); reader.Read(); Assert.Equal(Convert.ToInt32(data2[0]), reader.GetField("One")); Assert.Equal(Convert.ToInt32(data2[1]), reader.GetField("Two")); } [Fact] public void GetFieldByNameAndIndexTest() { var data1 = new[] { "One", "One" }; var data2 = new[] { "1", "2" }; var parserMock = new ParserMock(); parserMock.Add(data1); parserMock.Add(data2); var reader = new CsvReader(parserMock); reader.Read(); reader.ReadHeader(); reader.Read(); Assert.Equal(Convert.ToInt32(data2[0]), reader.GetField("One", 0)); Assert.Equal(Convert.ToInt32(data2[1]), reader.GetField("One", 1)); } [Fact] public void GetMissingFieldByNameTest() { var config = new CsvConfiguration(CultureInfo.InvariantCulture) { MissingFieldFound = null, }; var data1 = new[] { "One", "Two" }; var data2 = new[] { "1", "2" }; var parserMock = new ParserMock(config); parserMock.Add(data1); parserMock.Add(data2); var reader = new CsvReader(parserMock); reader.Read(); reader.ReadHeader(); Assert.Null(reader.GetField("blah")); } [Fact] public void GetMissingFieldByNameStrictTest() { var parserMock = new ParserMock { { "One", "Two" }, { "1", "2" }, }; var reader = new CsvReader(parserMock); reader.Read(); reader.ReadHeader(); Assert.Throws(() => reader.GetField("blah")); } [Fact] public void GetMissingFieldByIndexStrictTest() { var parserMock = new ParserMock { { "One", "Two" }, { "1", "2" }, null, }; var reader = new CsvReader(parserMock); reader.Read(); Assert.Throws(() => reader.GetField(2)); } [Fact] public void GetMissingFieldGenericByIndexStrictTest() { var parserMock = new ParserMock { { "One", "Two" }, { "1", "2" }, null, }; var config = new CsvConfiguration(CultureInfo.InvariantCulture) { IgnoreBlankLines = false, }; var reader = new CsvReader(parserMock); reader.Read(); Assert.Throws(() => reader.GetField(2)); } [Fact] public void GetMissingFieldByIndexStrictOffTest() { var config = new CsvConfiguration(CultureInfo.InvariantCulture) { MissingFieldFound = null, }; var parserMock = new ParserMock(config) { { "One", "Two" }, { "1", "2" }, null, }; var reader = new CsvReader(parserMock); reader.Read(); Assert.Null(reader.GetField(2)); } [Fact] public void GetMissingFieldGenericByIndexStrictOffTest() { var config = new CsvConfiguration(CultureInfo.InvariantCulture) { MissingFieldFound = null, }; var parserMock = new ParserMock(config) { { "One", "Two" }, { "1", "2" }, null, }; var reader = new CsvReader(parserMock); reader.Read(); Assert.Null(reader.GetField(2)); } [Fact] public void GetFieldByNameNoHeaderExceptionTest() { var config = new CsvConfiguration(CultureInfo.InvariantCulture) { HasHeaderRecord = false, }; var parserMock = new ParserMock(config) { { "1", "2" } }; var reader = new CsvReader(parserMock); reader.Read(); Assert.Throws(() => reader.GetField("One")); } [Fact] public void GetRecordWithDuplicateHeaderFields() { var config = new CsvConfiguration(CultureInfo.InvariantCulture) { MissingFieldFound = null, }; var parserMock = new ParserMock(config) { { "Field1", "Field1" }, { "Field1", "Field1" }, }; var reader = new CsvReader(parserMock); reader.Read(); } [Fact] public void GetRecordGenericTest() { var config = new CsvConfiguration(CultureInfo.InvariantCulture) { MissingFieldFound = null, HeaderValidated = null, }; var headerData = new[] { "IntColumn", "String Column", "GuidColumn", }; var recordData = new[] { "1", "string column", Guid.NewGuid().ToString(), }; var csvParserMock = new ParserMock(config) { headerData, recordData, null, }; var csv = new CsvReader(csvParserMock); csv.Context.RegisterClassMap(); csv.Read(); var record = csv.GetRecord(); Assert.Equal(Convert.ToInt32(recordData[0]), record.IntColumn); Assert.Equal(recordData[1], record.StringColumn); Assert.Equal("test", record.TypeConvertedColumn); Assert.Equal(Convert.ToInt32(recordData[0]), record.FirstColumn); Assert.Equal(new Guid(recordData[2]), record.GuidColumn); } [Fact] public void GetRecordTest() { var config = new CsvConfiguration(CultureInfo.InvariantCulture) { MissingFieldFound = null, HeaderValidated = null, }; var headerData = new[] { "IntColumn", "String Column", "GuidColumn", }; var recordData = new[] { "1", "string column", Guid.NewGuid().ToString(), }; var csvParserMock = new ParserMock(config) { headerData, recordData, null, }; var csv = new CsvReader(csvParserMock); csv.Context.RegisterClassMap(); csv.Read(); var record = (TestRecord)csv.GetRecord(typeof(TestRecord)); Assert.Equal(Convert.ToInt32(recordData[0]), record.IntColumn); Assert.Equal(recordData[1], record.StringColumn); Assert.Equal("test", record.TypeConvertedColumn); Assert.Equal(Convert.ToInt32(recordData[0]), record.FirstColumn); Assert.Equal(new Guid(recordData[2]), record.GuidColumn); } [Fact] public void GetRecordsGenericTest() { var config = new CsvConfiguration(CultureInfo.InvariantCulture) { MissingFieldFound = null, HeaderValidated = null, }; var headerData = new[] { "IntColumn", "String Column", "GuidColumn", }; var guid = Guid.NewGuid(); var csvParserMock = new ParserMock(config) { headerData, { "1", "string column 1", guid.ToString() }, { "2", "string column 2", guid.ToString() }, }; var csv = new CsvReader(csvParserMock); csv.Context.RegisterClassMap(); var records = csv.GetRecords().ToList(); Assert.Equal(2, records.Count); for (var i = 1; i <= records.Count; i++) { var record = records[i - 1]; Assert.Equal(i, record.IntColumn); Assert.Equal("string column " + i, record.StringColumn); Assert.Equal("test", record.TypeConvertedColumn); Assert.Equal(i, record.FirstColumn); Assert.Equal(guid, record.GuidColumn); } } [Fact] public void GetRecordsTest() { var config = new CsvConfiguration(CultureInfo.InvariantCulture) { MissingFieldFound = null, HeaderValidated = null, }; var headerData = new[] { "IntColumn", "String Column", "GuidColumn", }; var guid = Guid.NewGuid(); var csvParserMock = new ParserMock(config) { headerData, { "1", "string column 1", guid.ToString() }, { "2", "string column 2", guid.ToString() }, }; var csv = new CsvReader(csvParserMock); csv.Context.RegisterClassMap(); var records = csv.GetRecords(typeof(TestRecord)).ToList(); Assert.Equal(2, records.Count); for (var i = 1; i <= records.Count; i++) { var record = (TestRecord)records[i - 1]; Assert.Equal(i, record.IntColumn); Assert.Equal("string column " + i, record.StringColumn); Assert.Equal("test", record.TypeConvertedColumn); Assert.Equal(i, record.FirstColumn); Assert.Equal(guid, record.GuidColumn); } } [Fact] public void GetRecordsWithDuplicateHeaderNames() { var config = new CsvConfiguration(CultureInfo.InvariantCulture) { MissingFieldFound = null, }; var headerData = new[] { "Column", "Column", "Column" }; var csvParserMock = new ParserMock(config) { headerData, { "one", "two", "three" }, { "one", "two", "three" }, }; var csv = new CsvReader(csvParserMock); csv.Context.RegisterClassMap(); var records = csv.GetRecords().ToList(); Assert.Equal(2, records.Count); for (var i = 1; i <= records.Count; i++) { var record = records[i - 1]; Assert.Equal("one", record.Column1); Assert.Equal("two", record.Column2); Assert.Equal("three", record.Column3); } } [Fact] public void GetRecordEmptyFileWithHeaderOnTest() { var parserMock = new ParserMock { null, }; var csvReader = new CsvReader(parserMock); try { csvReader.Read(); csvReader.ReadHeader(); csvReader.Read(); throw new XUnitException(); } catch (ReaderException) { } } [Fact] public void GetRecordEmptyValuesNullableTest() { var stream = new MemoryStream(); var writer = new StreamWriter(stream); writer.WriteLine("StringColumn,IntColumn,GuidColumn"); writer.WriteLine("one,1,11111111-1111-1111-1111-111111111111"); writer.WriteLine(",,"); writer.WriteLine("three,3,33333333-3333-3333-3333-333333333333"); writer.Flush(); stream.Position = 0; var reader = new StreamReader(stream); var csvReader = new CsvReader(reader, CultureInfo.InvariantCulture); csvReader.Read(); var record = csvReader.GetRecord(); Assert.NotNull(record); Assert.Equal("one", record.StringColumn); Assert.Equal(1, record.IntColumn); Assert.Equal(new Guid("11111111-1111-1111-1111-111111111111"), record.GuidColumn); csvReader.Read(); record = csvReader.GetRecord(); Assert.NotNull(record); Assert.Equal(string.Empty, record.StringColumn); Assert.Null(record.IntColumn); Assert.Null(record.GuidColumn); csvReader.Read(); record = csvReader.GetRecord(); Assert.NotNull(record); Assert.Equal("three", record.StringColumn); Assert.Equal(3, record.IntColumn); Assert.Equal(new Guid("33333333-3333-3333-3333-333333333333"), record.GuidColumn); } [Fact] public void CaseInsensitiveHeaderMatchingTest() { var config = new CsvConfiguration(CultureInfo.InvariantCulture) { PrepareHeaderForMatch = args => args.Header.ToLower(), }; using (var stream = new MemoryStream()) using (var writer = new StreamWriter(stream)) using (var reader = new StreamReader(stream)) using (var csv = new CsvReader(reader, config)) { writer.WriteLine("One,Two,Three"); writer.WriteLine("1,2,3"); writer.Flush(); stream.Position = 0; csv.Read(); csv.ReadHeader(); csv.Read(); Assert.Equal("1", csv.GetField("one")); Assert.Equal("2", csv.GetField("TWO")); Assert.Equal("3", csv.GetField("ThreE")); } } [Fact] public void SpacesInHeaderTest() { var config = new CsvConfiguration(CultureInfo.InvariantCulture) { PrepareHeaderForMatch = args => Regex.Replace(args.Header, @"\s", string.Empty), }; var parserMock = new ParserMock(config) { { " Int Column ", " String Column " }, { "1", "one" }, }; var reader = new CsvReader(parserMock); var data = reader.GetRecords().ToList(); Assert.NotNull(data); Assert.Single(data); Assert.Equal(1, data[0].IntColumn); Assert.Equal("one", data[0].StringColumn); } [Fact] public void BooleanTypeConverterTest() { var stream = new MemoryStream(); var writer = new StreamWriter(stream); writer.WriteLine("BoolColumn,BoolNullableColumn,StringColumn"); writer.WriteLine("true,true,1"); writer.WriteLine("True,True,2"); writer.WriteLine("1,1,3"); writer.WriteLine("false,false,4"); writer.WriteLine("False,False,5"); writer.WriteLine("0,0,6"); writer.Flush(); stream.Position = 0; var reader = new StreamReader(stream); var csvReader = new CsvReader(reader, CultureInfo.InvariantCulture); var records = csvReader.GetRecords().ToList(); Assert.True(records[0].BoolColumn); Assert.True(records[0].BoolNullableColumn); Assert.True(records[1].BoolColumn); Assert.True(records[1].BoolNullableColumn); Assert.True(records[2].BoolColumn); Assert.True(records[2].BoolNullableColumn); Assert.False(records[3].BoolColumn); Assert.False(records[3].BoolNullableColumn); Assert.False(records[4].BoolColumn); Assert.False(records[4].BoolNullableColumn); Assert.False(records[5].BoolColumn); Assert.False(records[5].BoolNullableColumn); } [Fact] public void SkipEmptyRecordsTest() { var config = new CsvConfiguration(CultureInfo.InvariantCulture) { HasHeaderRecord = false, ShouldSkipRecord = args => args.Row.Parser.Record.All(string.IsNullOrWhiteSpace), }; var parserMock = new ParserMock(config) { { "1", "2", "3" }, { "", "", "" }, { "4", "5", "6" }, }; var reader = new CsvReader(parserMock); reader.Read(); Assert.Equal("1", reader.Parser.Record[0]); Assert.Equal("2", reader.Parser.Record[1]); Assert.Equal("3", reader.Parser.Record[2]); reader.Read(); Assert.Equal("4", reader.Parser.Record[0]); Assert.Equal("5", reader.Parser.Record[1]); Assert.Equal("6", reader.Parser.Record[2]); Assert.False(reader.Read()); } [Fact] public void SkipRecordCallbackTest() { var config = new CsvConfiguration(CultureInfo.InvariantCulture) { HasHeaderRecord = false, ShouldSkipRecord = args => args.Row[1] == "2", }; var parserMock = new ParserMock(config) { { "1", "2", "3" }, { " ", "", "" }, { "4", "5", "6" }, }; var reader = new CsvReader(parserMock); reader.Read(); Assert.Equal(" ", reader.Parser.Record[0]); Assert.Equal("", reader.Parser.Record[1]); Assert.Equal("", reader.Parser.Record[2]); reader.Read(); Assert.Equal("4", reader.Parser.Record[0]); Assert.Equal("5", reader.Parser.Record[1]); Assert.Equal("6", reader.Parser.Record[2]); Assert.False(reader.Read()); } [Fact] public void MultipleGetRecordsCalls() { var config = new CsvConfiguration(CultureInfo.InvariantCulture) { HeaderValidated = null, MissingFieldFound = null, }; using (var stream = new MemoryStream()) using (var writer = new StreamWriter(stream)) using (var reader = new StreamReader(stream)) using (var csvReader = new CsvReader(reader, config)) { writer.WriteLine("IntColumn,String Column"); writer.WriteLine("1,one"); writer.WriteLine("2,two"); writer.Flush(); stream.Position = 0; csvReader.Context.RegisterClassMap(); var records = csvReader.GetRecords(); Assert.Equal(2, records.Count()); Assert.Empty(records); } } [Fact] public void IgnoreExceptionsTest() { var callbackCount = 0; var config = new CsvConfiguration(CultureInfo.InvariantCulture) { ReadingExceptionOccurred = (ex) => { callbackCount++; return false; }, }; var parserMock = new ParserMock(config) { { "BoolColumn", "BoolNullableColumn", "StringColumn" }, { "1", "1", "one" }, { "two", "1", "two" }, { "1", "1", "three" }, { "four", "1", "four" }, { "1", "1", "five" }, }; var csv = new CsvReader(parserMock); var records = csv.GetRecords().ToList(); Assert.NotNull(records); Assert.Equal(3, records.Count); Assert.Equal(2, callbackCount); Assert.Equal("one", records[0].StringColumn); Assert.Equal("three", records[1].StringColumn); Assert.Equal("five", records[2].StringColumn); } [Fact] public void ReadStructRecordsTest() { var parserMock = new ParserMock { { "Id", "Name" }, { "1", "one" }, { "2", "two" }, }; var csv = new CsvReader(parserMock); var records = csv.GetRecords().ToList(); Assert.NotNull(records); Assert.Equal(2, records.Count); Assert.Equal(1, records[0].Id); Assert.Equal("one", records[0].Name); Assert.Equal(2, records[1].Id); Assert.Equal("two", records[1].Name); } [Fact] public void WriteStructReferenceRecordsTest() { var parserMock = new ParserMock { { "Id", "Name" }, { "1", "one" }, }; var csv = new CsvReader(parserMock); csv.Context.RegisterClassMap(); var records = csv.GetRecords().ToList(); Assert.NotNull(records); Assert.Single(records); Assert.Equal(1, records[0].Test.Id); Assert.Equal("one", records[0].Test.Name); } [Fact] public void ReadPrimitiveRecordsHasHeaderTrueTest() { var parserMock = new ParserMock { { "Id" }, { "1" }, { "2" }, }; var csv = new CsvReader(parserMock); var records = csv.GetRecords().ToList(); Assert.NotNull(records); Assert.Equal(2, records.Count); Assert.Equal(1, records[0]); Assert.Equal(2, records[1]); } [Fact] public void ReadPrimitiveRecordsHasHeaderFalseTest() { var config = new CsvConfiguration(CultureInfo.InvariantCulture) { HasHeaderRecord = false, }; var parserMock = new ParserMock(config) { { "1" }, { "2" }, }; var csv = new CsvReader(parserMock); var records = csv.GetRecords().ToList(); Assert.NotNull(records); Assert.Equal(2, records.Count); Assert.Equal(1, records[0]); Assert.Equal(2, records[1]); } [Fact] public void TrimHeadersTest() { var config = new CsvConfiguration(CultureInfo.InvariantCulture) { MissingFieldFound = null, PrepareHeaderForMatch = args => args.Header.Trim(), }; var parserMock = new ParserMock(config) { { " one ", " two three " }, { "1", "2" }, }; var reader = new CsvReader(parserMock); reader.Read(); reader.ReadHeader(); reader.Read(); Assert.Equal("1", reader.GetField("one")); Assert.Equal("2", reader.GetField("two three")); Assert.Null(reader.GetField("twothree")); } [Fact] public void RowTest() { var config = new CsvConfiguration(CultureInfo.InvariantCulture) { HasHeaderRecord = false, }; var parserMock = new ParserMock(config) { { "1", "one" }, { "2", "two" }, }; var csv = new CsvReader(parserMock); csv.Read(); Assert.Equal(1, csv.Parser.Row); csv.Read(); Assert.Equal(2, csv.Parser.Row); } [Fact] public void DoNotIgnoreBlankLinesTest() { var config = new CsvConfiguration(CultureInfo.InvariantCulture) { Delimiter = ",", IgnoreBlankLines = false, MissingFieldFound = null, }; using (var stream = new MemoryStream()) using (var reader = new StreamReader(stream)) using (var writer = new StreamWriter(stream)) using (var csv = new CsvReader(reader, config)) { csv.Context.RegisterClassMap(); writer.WriteLine("Id,Name"); writer.WriteLine("1,one"); writer.WriteLine(","); writer.WriteLine(""); writer.WriteLine("2,two"); writer.Flush(); stream.Position = 0; var records = csv.GetRecords().ToList(); Assert.Equal(1, records[0].Id); Assert.Equal("one", records[0].Name); Assert.Null(records[1].Id); Assert.Equal("", records[1].Name); Assert.Null(records[2].Id); Assert.Equal("", records[2].Name); Assert.Equal(2, records[3].Id); Assert.Equal("two", records[3].Name); } } [Fact] public void WriteNestedHeadersTest() { var config = new CsvConfiguration(CultureInfo.InvariantCulture) { ReferenceHeaderPrefix = args => $"{args.MemberName}.", }; using (var stream = new MemoryStream()) using (var reader = new StreamReader(stream)) using (var writer = new StreamWriter(stream)) using (var csv = new CsvReader(reader, config)) { writer.WriteLine("Simple1.Id,Simple1.Name,Simple2.Id,Simple2.Name"); writer.WriteLine("1,one,2,two"); writer.Flush(); stream.Position = 0; var records = csv.GetRecords().ToList(); Assert.NotNull(records); Assert.Equal(1, records[0].Simple1.Id); Assert.Equal("one", records[0].Simple1.Name); Assert.Equal(2, records[0].Simple2.Id); Assert.Equal("two", records[0].Simple2.Name); } } [Fact] public void ReaderDynamicHasHeaderTest() { var parserMock = new ParserMock { { "Id", "Name" }, { "1", "one" }, { "2", "two" }, null }; var csv = new CsvReader(parserMock); csv.Read(); var row = csv.GetRecord(); Assert.Equal("1", row.Id); Assert.Equal("one", row.Name); } [Fact] public void ReaderDynamicNoHeaderTest() { var config = new CsvConfiguration(CultureInfo.InvariantCulture) { HasHeaderRecord = false, }; var parserMock = new ParserMock(config) { { "1", "one" }, { "2", "two" }, null, }; var csv = new CsvReader(parserMock); csv.Read(); var row = csv.GetRecord(); Assert.Equal("1", row.Field1); Assert.Equal("one", row.Field2); } [Fact] public void TryGetFieldNotInHeaderTest() // https://github.com/JoshClose/CsvHelper/issues/1981 { var parserMock = new ParserMock { { "Id", "piz z/a"}, { "1", "one" }, { "Id" }, { "2" } }; var csv = new CsvReader(parserMock); csv.Read(); csv.ReadHeader(); csv.Read(); csv.GetField("piz z/a"); csv.Read(); csv.ReadHeader(); csv.Read(); Assert.False(csv.TryGetField("piz z/a", out var tmp)); } private class Nested { public Simple Simple1 { get; set; } public Simple Simple2 { get; set; } } private class Simple { public int? Id { get; set; } public string Name { get; set; } } private sealed class SimpleMap : ClassMap { public SimpleMap() { Map(m => m.Id); Map(m => m.Name); } } private class TestStructParent { public TestStruct Test { get; set; } } private sealed class TestStructParentMap : ClassMap { public TestStructParentMap() { References(m => m.Test); } } private struct TestStruct { public int Id { get; set; } public string Name { get; set; } } private sealed class TestStructMap : ClassMap { public TestStructMap() { Map(m => m.Id); Map(m => m.Name); } } private class OnlyFields { public string Name; } private sealed class OnlyFieldsMap : ClassMap { public OnlyFieldsMap() { Map(m => m.Name); } } private class TestBoolean { public bool BoolColumn { get; set; } public bool BoolNullableColumn { get; set; } public string StringColumn { get; set; } } private class TestDefaultValues { public int IntColumn { get; set; } public string StringColumn { get; set; } } private sealed class TestDefaultValuesMap : ClassMap { public TestDefaultValuesMap() { Map(m => m.IntColumn).Default(-1); Map(m => m.StringColumn).Default((string)null); } } private class TestNullable { public int? IntColumn { get; set; } public string StringColumn { get; set; } public Guid? GuidColumn { get; set; } } [DebuggerDisplay("IntColumn = {IntColumn}, StringColumn = {StringColumn}, IgnoredColumn = {IgnoredColumn}, TypeConvertedColumn = {TypeConvertedColumn}, FirstColumn = {FirstColumn}")] private class TestRecord { public int IntColumn { get; set; } public string StringColumn { get; set; } public string IgnoredColumn { get; set; } public string TypeConvertedColumn { get; set; } public int FirstColumn { get; set; } public Guid GuidColumn { get; set; } public int NoMatchingFields { get; set; } } private sealed class TestRecordMap : ClassMap { public TestRecordMap() { Map(m => m.IntColumn).TypeConverter(); Map(m => m.StringColumn).Name("String Column"); Map(m => m.TypeConvertedColumn).Index(1).TypeConverter(); Map(m => m.FirstColumn).Index(0); Map(m => m.GuidColumn); Map(m => m.NoMatchingFields); } } private class TestRecordDuplicateHeaderNames { public string Column1 { get; set; } public string Column2 { get; set; } public string Column3 { get; set; } } private sealed class TestRecordDuplicateHeaderNamesMap : ClassMap { public TestRecordDuplicateHeaderNamesMap() { Map(m => m.Column1).Name("Column").NameIndex(0); Map(m => m.Column2).Name("Column").NameIndex(1); Map(m => m.Column3).Name("Column").NameIndex(2); } } private class TestTypeConverter : DefaultTypeConverter { public override object ConvertFromString(string text, IReaderRow row, MemberMapData propertyMapData) { return "test"; } } } }