// Copyright 2016 Google Inc. All Rights Reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package com.google.api.ads.common.lib.utils; import static org.junit.Assert.assertArrayEquals; import static org.junit.Assert.assertEquals; import com.google.common.base.CharMatcher; import com.google.common.base.Charsets; import com.google.common.base.Splitter; import com.google.common.collect.Iterables; import com.google.common.collect.Lists; import com.google.common.collect.Maps; import com.google.common.io.Files; import org.junit.Before; import org.junit.Rule; import org.junit.Test; import org.junit.rules.ExpectedException; import org.junit.rules.TemporaryFolder; import org.junit.runner.RunWith; import org.junit.runners.Parameterized; import org.junit.runners.Parameterized.Parameters; import java.io.File; import java.io.FileReader; import java.io.IOException; import java.io.Reader; import java.util.Arrays; import java.util.List; import java.util.Map; import java.util.Map.Entry; /** * Tests for {@link CsvFiles}. */ @RunWith(Parameterized.class) public class CsvFilesTest { @Rule public ExpectedException thrown = ExpectedException.none(); @Rule public TemporaryFolder tempFolder = new TemporaryFolder(); private String csvString = String.format("a,a1,a2,a3%nb,b1,b2%nc,c1%n"); /** Data list, before any mutations based on {@code headerPresent}. */ private List<String[]> originalDataList = Lists.<String[]>newArrayList( new String[] {"a", "a1", "a2", "a3"}, new String[] {"b", "b1", "b2"}, new String[] {"c", "c1"}); /** Data list, modified based on {@code headerPresent}. */ private List<String[]> dataList = Lists.newArrayList(originalDataList); /** File containing {@code csvString} as its contents. */ private File csvStringFile; /** The {@code headerPresent} argument to pass to methods being tested. */ private final boolean headerPresent; public CsvFilesTest(boolean headerPresent) { this.headerPresent = headerPresent; } @Parameters(name = "headerPresent={0}") public static List<Object[]> data() { List<Object[]> data = Lists.newArrayList(); data.add(new Object[] {Boolean.FALSE}); data.add(new Object[] {Boolean.TRUE}); return data; } @Before public void setUp() throws Exception { csvStringFile = tempFolder.newFile(); Files.write(csvString, csvStringFile, Charsets.UTF_8); if (headerPresent) { dataList.remove(0); } } @Test public void testWriteCsv() throws IOException { File csvFile = tempFolder.newFile(); CsvFiles.writeCsv(dataList, csvFile.getPath()); List<String> actualLines = Files.readLines(csvFile, Charsets.UTF_8); assertEquals(dataList.size(), actualLines.size()); Splitter splitter = Splitter.on(',').trimResults(CharMatcher.is('"')); for (int i = 0; i < dataList.size(); i++) { String actualLine = actualLines.get(i); String[] actualValues = Iterables.toArray(splitter.split(actualLine), String.class); String[] expectedValues = dataList.get(i); assertArrayEquals("Row " + i + " does not match", expectedValues, actualValues); } } @Test public void testWriteCsv_nullData_fails() throws IOException { thrown.expect(NullPointerException.class); thrown.expectMessage("Null CSV data"); CsvFiles.writeCsv(null, "/tmp/foobar"); } @Test public void testWriteCsv_null_fails() throws IOException { thrown.expect(NullPointerException.class); thrown.expectMessage("Null file name"); CsvFiles.writeCsv(dataList, null); } @Test public void testGetCsvDataMap() throws IOException { Map<String, String> expectedDataMap = Maps.newHashMap(); for (String[] data : dataList) { expectedDataMap.put(data[0], data[1]); } Map<String, String> actualDataMap = CsvFiles.getCsvDataMap(csvStringFile.getPath(), headerPresent); assertEquals(expectedDataMap, actualDataMap); } @Test public void testGetCsvDataMapArray() throws IOException { Map<String, String[]> actualDataMapArray = CsvFiles.getCsvDataMapArray(csvStringFile.getPath(), headerPresent); Map<String, List<String>> actualDataMapList = Maps.newHashMap(); for (Entry<String, String[]> actualDataMapEntry : actualDataMapArray.entrySet()) { actualDataMapList.put( actualDataMapEntry.getKey(), Arrays.asList(actualDataMapEntry.getValue())); } Map<String, List<String>> expectedDataMap = Maps.newHashMap(); for (String[] rowData : dataList) { expectedDataMap.put( rowData[0], Arrays.asList(Arrays.copyOfRange(rowData, 1, rowData.length))); } assertEquals(expectedDataMap, actualDataMapList); } @Test public void testGetCsvDataArray() throws IOException { List<String[]> actualDataList = CsvFiles.getCsvDataArray(csvStringFile.getPath(), headerPresent); assertEquals(dataList.size(), actualDataList.size()); for (int i = 0; i < actualDataList.size(); i++) { assertArrayEquals("Row " + i + " does not match", dataList.get(i), actualDataList.get(i)); } } @Test public void testGetCsvDataArray_fromReader() throws IOException { Reader reader = new FileReader(csvStringFile); List<String[]> actualDataArray = CsvFiles.getCsvDataArray(reader, headerPresent); assertEquals(dataList.size(), actualDataArray.size()); for (int i = 0; i < actualDataArray.size(); i++) { assertArrayEquals("Row " + i + " does not match", dataList.get(i), actualDataArray.get(i)); } // Reader should be closed (not ready). thrown.expect(IOException.class); thrown.expectMessage("Stream closed"); reader.ready(); } @Test public void testGetCsvDataListMap() throws IOException { // Construct the expected list of row maps. List<Map<String, String>> expectedDataListMap = Lists.newArrayList(); String[] columnHeaders = new String[4]; if (headerPresent) { columnHeaders = originalDataList.get(0); } else { for (int i = 0; i < columnHeaders.length; i++) { columnHeaders[i] = Integer.valueOf(i).toString(); } } for (String[] rowData : dataList) { Map<String, String> rowMap = Maps.newHashMap(); for (int i = 0; i < rowData.length; i++) { rowMap.put(columnHeaders[i], rowData[i]); } expectedDataListMap.add(rowMap); } // Verify CsvFiles.getCsvDataListMap returns the expected list of row maps. List<Map<String, String>> actualDataListMap = CsvFiles.getCsvDataListMap(csvStringFile.getPath(), headerPresent); assertEquals(expectedDataListMap, actualDataListMap); } @Test public void testGetCsvDataByColumn() throws IOException { List<List<String>> expectedData = Lists.newArrayList(); expectedData.add(Lists.newArrayList("a", "b", "c")); expectedData.add(Lists.newArrayList("a1", "b1", "c1")); for (int column = 0; column < 2; column++) { List<String> actualDataByColumn = CsvFiles.getCsvDataByColumn(csvStringFile.getPath(), column, headerPresent); List<String> expectedDataByColumn = expectedData.get(column); if (headerPresent) { expectedDataByColumn.remove(0); } assertEquals( "Values for column " + column + " do not match", expectedDataByColumn, actualDataByColumn); } } }