This is an automated email from the ASF dual-hosted git repository.
hansva pushed a commit to branch 2.18.1-patch
in repository https://gitbox.apache.org/repos/asf/hop.git
The following commit(s) were added to refs/heads/2.18.1-patch by this push:
new 3a505fa3ec rownum not working on text file input, fixes #7255 (#7259)
3a505fa3ec is described below
commit 3a505fa3ecdb4757876ef6e92f0faa41d2097b0d
Author: Hans Van Akelyen <[email protected]>
AuthorDate: Wed Jun 10 15:05:08 2026 +0200
rownum not working on text file input, fixes #7255 (#7259)
---
.../transforms/0040-text-file-input-rownum.hpl | 327 +++++++++++++++++++++
.../transforms/files/text-file-input-rownum.txt | 3 +
.../transforms/main-0040-text-file-input.hwf | 77 +++--
.../fileinput/text/TextFileInputMeta.java | 4 +-
.../fileinput/text/TextFileInputUtils.java | 21 +-
.../text/TextFileInputContentParsingTest.java | 95 ++++++
6 files changed, 495 insertions(+), 32 deletions(-)
diff --git a/integration-tests/transforms/0040-text-file-input-rownum.hpl
b/integration-tests/transforms/0040-text-file-input-rownum.hpl
new file mode 100644
index 0000000000..24e19133ee
--- /dev/null
+++ b/integration-tests/transforms/0040-text-file-input-rownum.hpl
@@ -0,0 +1,327 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+Licensed to the Apache Software Foundation (ASF) under one or more
+contributor license agreements. See the NOTICE file distributed with
+this work for additional information regarding copyright ownership.
+The ASF licenses this file to You 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.
+
+-->
+<pipeline>
+ <info>
+ <name>0040-text-file-input-rownum</name>
+ <name_sync_with_filename>Y</name_sync_with_filename>
+ <description>Verifies the "Rownum in output" option of Text File Input is
actually populated</description>
+ <extended_description/>
+ <pipeline_version/>
+ <pipeline_type>Normal</pipeline_type>
+ <parameters>
+ </parameters>
+ <capture_transform_performance>N</capture_transform_performance>
+
<transform_performance_capturing_delay>1000</transform_performance_capturing_delay>
+
<transform_performance_capturing_size_limit>100</transform_performance_capturing_size_limit>
+ <created_user>-</created_user>
+ <created_date>2026/06/10 12:00:00.000</created_date>
+ <modified_user>-</modified_user>
+ <modified_date>2026/06/10 12:00:00.000</modified_date>
+ </info>
+ <notepads>
+ </notepads>
+ <order>
+ <hop>
+ <from>Read with rownum</from>
+ <to>Rownum is null?</to>
+ <enabled>Y</enabled>
+ </hop>
+ <hop>
+ <from>Rownum is null?</from>
+ <to>Rownum is null - Abort</to>
+ <enabled>Y</enabled>
+ </hop>
+ <hop>
+ <from>Rownum is null?</from>
+ <to>Sum rownum</to>
+ <enabled>Y</enabled>
+ </hop>
+ <hop>
+ <from>Sum rownum</from>
+ <to>Check totals</to>
+ <enabled>Y</enabled>
+ </hop>
+ <hop>
+ <from>Check totals</from>
+ <to>Success</to>
+ <enabled>Y</enabled>
+ </hop>
+ <hop>
+ <from>Check totals</from>
+ <to>Wrong totals - Abort</to>
+ <enabled>Y</enabled>
+ </hop>
+ </order>
+ <transform>
+ <name>Read with rownum</name>
+ <type>TextFileInput2</type>
+ <description/>
+ <distribute>Y</distribute>
+ <custom_distribution/>
+ <copies>1</copies>
+ <partitioning>
+ <method>none</method>
+ <schema_name/>
+ </partitioning>
+ <accept_filenames>N</accept_filenames>
+ <passing_through_fields>N</passing_through_fields>
+ <accept_field/>
+ <accept_transform_name/>
+ <separator>,</separator>
+ <enclosure>"</enclosure>
+ <enclosure_breaks>N</enclosure_breaks>
+ <escapechar/>
+ <header>N</header>
+ <nr_headerlines>1</nr_headerlines>
+ <footer>N</footer>
+ <nr_footerlines>1</nr_footerlines>
+ <line_wrapped>N</line_wrapped>
+ <nr_wraps>1</nr_wraps>
+ <layout_paged>N</layout_paged>
+ <nr_lines_per_page>80</nr_lines_per_page>
+ <nr_lines_doc_header>0</nr_lines_doc_header>
+ <noempty>Y</noempty>
+ <include>N</include>
+ <include_field/>
+ <rownum>Y</rownum>
+ <rownumByFile>N</rownumByFile>
+ <rownum_field>rownr</rownum_field>
+ <format>mixed</format>
+ <encoding>UTF-8</encoding>
+ <length>Characters</length>
+ <add_to_result_filenames>N</add_to_result_filenames>
+ <file>
+ <name>${PROJECT_HOME}/files/text-file-input-rownum.txt</name>
+ <filemask/>
+ <exclude_filemask/>
+ <file_required>N</file_required>
+ <include_subfolders>N</include_subfolders>
+ <type>CSV</type>
+ <compression>None</compression>
+ </file>
+ <filters>
+ </filters>
+ <fields>
+ <field>
+ <name>value</name>
+ <type>String</type>
+ <format/>
+ <currency>$</currency>
+ <decimal>.</decimal>
+ <group>,</group>
+ <nullif/>
+ <ifnull/>
+ <position>-1</position>
+ <length>20</length>
+ <precision>-1</precision>
+ <trim_type>none</trim_type>
+ <repeat>N</repeat>
+ </field>
+ </fields>
+ <limit>0</limit>
+ <error_ignored>N</error_ignored>
+ <skip_bad_files>N</skip_bad_files>
+ <file_error_field/>
+ <file_error_message_field/>
+ <error_line_skipped>N</error_line_skipped>
+ <error_count_field/>
+ <error_fields_field/>
+ <error_text_field/>
+ <bad_line_files_destination_directory/>
+ <bad_line_files_extension>warning</bad_line_files_extension>
+ <error_line_files_destination_directory/>
+ <error_line_files_extension>error</error_line_files_extension>
+ <line_number_files_destination_directory/>
+ <line_number_files_extension>line</line_number_files_extension>
+ <date_format_lenient>Y</date_format_lenient>
+ <date_format_locale>en_US</date_format_locale>
+ <attributes/>
+ <GUI>
+ <xloc>128</xloc>
+ <yloc>96</yloc>
+ </GUI>
+ </transform>
+ <transform>
+ <name>Rownum is null?</name>
+ <type>FilterRows</type>
+ <description/>
+ <distribute>Y</distribute>
+ <custom_distribution/>
+ <copies>1</copies>
+ <partitioning>
+ <method>none</method>
+ <schema_name/>
+ </partitioning>
+ <send_true_to>Rownum is null - Abort</send_true_to>
+ <send_false_to>Sum rownum</send_false_to>
+ <compare>
+ <condition>
+ <negated>N</negated>
+ <leftvalue>rownr</leftvalue>
+ <function>IS NULL</function>
+ <rightvalue/>
+ </condition>
+ </compare>
+ <attributes/>
+ <GUI>
+ <xloc>288</xloc>
+ <yloc>96</yloc>
+ </GUI>
+ </transform>
+ <transform>
+ <name>Rownum is null - Abort</name>
+ <type>Abort</type>
+ <description/>
+ <distribute>Y</distribute>
+ <custom_distribution/>
+ <copies>1</copies>
+ <partitioning>
+ <method>none</method>
+ <schema_name/>
+ </partitioning>
+ <abort_option>ABORT_WITH_ERROR</abort_option>
+ <always_log_rows>Y</always_log_rows>
+ <message>Rownum in output is null - the "Rownum in output" option is not
being populated</message>
+ <row_threshold>0</row_threshold>
+ <attributes/>
+ <GUI>
+ <xloc>288</xloc>
+ <yloc>256</yloc>
+ </GUI>
+ </transform>
+ <transform>
+ <name>Sum rownum</name>
+ <type>GroupBy</type>
+ <description/>
+ <distribute>Y</distribute>
+ <custom_distribution/>
+ <copies>1</copies>
+ <partitioning>
+ <method>none</method>
+ <schema_name/>
+ </partitioning>
+ <all_rows>N</all_rows>
+ <ignore_aggregate>N</ignore_aggregate>
+ <field_ignore/>
+ <directory>${java.io.tmpdir}</directory>
+ <prefix>grp</prefix>
+ <add_linenr>N</add_linenr>
+ <linenr_fieldname/>
+ <give_back_row>N</give_back_row>
+ <group>
+ </group>
+ <fields>
+ <field>
+ <aggregate>sum_rownr</aggregate>
+ <subject>rownr</subject>
+ <type>SUM</type>
+ <valuefield/>
+ </field>
+ <field>
+ <aggregate>num_rows</aggregate>
+ <subject>value</subject>
+ <type>COUNT_ANY</type>
+ <valuefield/>
+ </field>
+ </fields>
+ <attributes/>
+ <GUI>
+ <xloc>448</xloc>
+ <yloc>96</yloc>
+ </GUI>
+ </transform>
+ <transform>
+ <name>Check totals</name>
+ <type>FilterRows</type>
+ <description/>
+ <distribute>Y</distribute>
+ <custom_distribution/>
+ <copies>1</copies>
+ <partitioning>
+ <method>none</method>
+ <schema_name/>
+ </partitioning>
+ <send_true_to>Success</send_true_to>
+ <send_false_to>Wrong totals - Abort</send_false_to>
+ <compare>
+ <condition>
+ <negated>N</negated>
+ <leftvalue>sum_rownr</leftvalue>
+ <function>=</function>
+ <rightvalue/>
+ <value>
+ <name>constant</name>
+ <type>Integer</type>
+ <text>6</text>
+ <length>-1</length>
+ <precision>0</precision>
+ <isnull>N</isnull>
+ <mask>####0;-####0</mask>
+ </value>
+ </condition>
+ </compare>
+ <attributes/>
+ <GUI>
+ <xloc>608</xloc>
+ <yloc>96</yloc>
+ </GUI>
+ </transform>
+ <transform>
+ <name>Wrong totals - Abort</name>
+ <type>Abort</type>
+ <description/>
+ <distribute>Y</distribute>
+ <custom_distribution/>
+ <copies>1</copies>
+ <partitioning>
+ <method>none</method>
+ <schema_name/>
+ </partitioning>
+ <abort_option>ABORT_WITH_ERROR</abort_option>
+ <always_log_rows>Y</always_log_rows>
+ <message>Unexpected rownum totals (expected 3 rows and sum
1+2+3=6)</message>
+ <row_threshold>0</row_threshold>
+ <attributes/>
+ <GUI>
+ <xloc>608</xloc>
+ <yloc>256</yloc>
+ </GUI>
+ </transform>
+ <transform>
+ <name>Success</name>
+ <type>Dummy</type>
+ <description/>
+ <distribute>Y</distribute>
+ <custom_distribution/>
+ <copies>1</copies>
+ <partitioning>
+ <method>none</method>
+ <schema_name/>
+ </partitioning>
+ <attributes/>
+ <GUI>
+ <xloc>768</xloc>
+ <yloc>96</yloc>
+ </GUI>
+ </transform>
+ <transform_error_handling>
+ </transform_error_handling>
+ <attributes/>
+</pipeline>
diff --git a/integration-tests/transforms/files/text-file-input-rownum.txt
b/integration-tests/transforms/files/text-file-input-rownum.txt
new file mode 100644
index 0000000000..85c30401ce
--- /dev/null
+++ b/integration-tests/transforms/files/text-file-input-rownum.txt
@@ -0,0 +1,3 @@
+alpha
+beta
+gamma
diff --git a/integration-tests/transforms/main-0040-text-file-input.hwf
b/integration-tests/transforms/main-0040-text-file-input.hwf
index 4c68f4100c..a2491549b5 100644
--- a/integration-tests/transforms/main-0040-text-file-input.hwf
+++ b/integration-tests/transforms/main-0040-text-file-input.hwf
@@ -22,45 +22,71 @@ limitations under the License.
<name_sync_with_filename>Y</name_sync_with_filename>
<description/>
<extended_description/>
- <workflow_version/>
<created_user>-</created_user>
- <created_date>2021/05/31 11:58:41.121</created_date>
<modified_user>-</modified_user>
+ <created_date>2021/05/31 11:58:41.121</created_date>
<modified_date>2021/05/31 11:58:41.121</modified_date>
- <parameters>
- </parameters>
+ <workflow_version/>
+ <parameters/>
<actions>
<action>
- <name>Start</name>
- <description/>
- <type>SPECIAL</type>
- <attributes/>
<repeat>N</repeat>
<schedulerType>0</schedulerType>
<intervalSeconds>0</intervalSeconds>
<intervalMinutes>60</intervalMinutes>
- <hour>12</hour>
- <minutes>0</minutes>
- <weekDay>1</weekDay>
<DayOfMonth>1</DayOfMonth>
- <parallel>N</parallel>
+ <weekDay>1</weekDay>
+ <minutes>0</minutes>
+ <hour>12</hour>
+ <doNotWaitOnFirstExecution>N</doNotWaitOnFirstExecution>
+ <name>Start</name>
+ <description/>
+ <type>SPECIAL</type>
+ <attributes/>
<xloc>128</xloc>
<yloc>112</yloc>
+ <parallel>N</parallel>
<attributes_hac/>
</action>
<action>
- <name>Run text-file-input test</name>
- <description/>
- <type>RunPipelineTests</type>
- <attributes/>
<test_names>
<test_name>
<name>0040-text-file-input-utf-bom UNIT</name>
</test_name>
</test_names>
+ <name>Run text-file-input test</name>
+ <description/>
+ <type>RunPipelineTests</type>
+ <attributes/>
+ <xloc>336</xloc>
+ <yloc>112</yloc>
<parallel>N</parallel>
- <xloc>416</xloc>
+ <attributes_hac/>
+ </action>
+ <action>
+ <filename>${PROJECT_HOME}/0040-text-file-input-rownum.hpl</filename>
+ <params_from_previous>N</params_from_previous>
+ <exec_per_row>N</exec_per_row>
+ <clear_rows>N</clear_rows>
+ <clear_files>N</clear_files>
+ <create_parent_folder>N</create_parent_folder>
+ <set_logfile>N</set_logfile>
+ <set_append_logfile>N</set_append_logfile>
+ <add_date>N</add_date>
+ <add_time>N</add_time>
+ <loglevel>Basic</loglevel>
+ <wait_until_finished>Y</wait_until_finished>
+ <parameters>
+ <pass_all_parameters>Y</pass_all_parameters>
+ </parameters>
+ <run_configuration>local</run_configuration>
+ <name>0040-text-file-input-rownum.hpl</name>
+ <description/>
+ <type>PIPELINE</type>
+ <attributes/>
+ <xloc>608</xloc>
<yloc>112</yloc>
+ <parallel>N</parallel>
<attributes_hac/>
</action>
</actions>
@@ -68,18 +94,21 @@ limitations under the License.
<hop>
<from>Start</from>
<to>Run text-file-input test</to>
- <enabled>Y</enabled>
<evaluation>Y</evaluation>
<unconditional>Y</unconditional>
+ <enabled>Y</enabled>
+ </hop>
+ <hop>
+ <from>Run text-file-input test</from>
+ <to>0040-text-file-input-rownum.hpl</to>
+ <evaluation>Y</evaluation>
+ <unconditional>N</unconditional>
+ <enabled>Y</enabled>
</hop>
</hops>
<notepads>
<notepad>
<note>Test reading CSV files with the CSV Input transform </note>
- <xloc>128</xloc>
- <yloc>208</yloc>
- <width>284</width>
- <heigth>26</heigth>
<fontname>Inter</fontname>
<fontsize>11</fontsize>
<fontbold>N</fontbold>
@@ -93,6 +122,10 @@ limitations under the License.
<bordercolorred>14</bordercolorred>
<bordercolorgreen>58</bordercolorgreen>
<bordercolorblue>90</bordercolorblue>
+ <xloc>128</xloc>
+ <yloc>208</yloc>
+ <width>284</width>
+ <height>-1</height>
</notepad>
</notepads>
<attributes/>
diff --git
a/plugins/transforms/textfile/src/main/java/org/apache/hop/pipeline/transforms/fileinput/text/TextFileInputMeta.java
b/plugins/transforms/textfile/src/main/java/org/apache/hop/pipeline/transforms/fileinput/text/TextFileInputMeta.java
index 9347b343ec..4c123242a9 100644
---
a/plugins/transforms/textfile/src/main/java/org/apache/hop/pipeline/transforms/fileinput/text/TextFileInputMeta.java
+++
b/plugins/transforms/textfile/src/main/java/org/apache/hop/pipeline/transforms/fileinput/text/TextFileInputMeta.java
@@ -664,12 +664,12 @@ public class TextFileInputMeta
@Override
public boolean isIncludeFilename() {
- return false;
+ return content.includeFilename;
}
@Override
public boolean isIncludeRowNumber() {
- return false;
+ return content.includeRowNumber;
}
public String[] getInfoTransforms() {
diff --git
a/plugins/transforms/textfile/src/main/java/org/apache/hop/pipeline/transforms/fileinput/text/TextFileInputUtils.java
b/plugins/transforms/textfile/src/main/java/org/apache/hop/pipeline/transforms/fileinput/text/TextFileInputUtils.java
index 53a81d4f43..b9b937112a 100644
---
a/plugins/transforms/textfile/src/main/java/org/apache/hop/pipeline/transforms/fileinput/text/TextFileInputUtils.java
+++
b/plugins/transforms/textfile/src/main/java/org/apache/hop/pipeline/transforms/fileinput/text/TextFileInputUtils.java
@@ -21,6 +21,7 @@ import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.List;
+import org.apache.commons.lang3.StringUtils;
import org.apache.hop.core.Const;
import org.apache.hop.core.exception.HopException;
import org.apache.hop.core.gui.ITextFileInputField;
@@ -536,42 +537,46 @@ public class TextFileInputUtils {
}
// Possibly add short filename...
- if (additionalOutputFields.getShortFilenameField() != null) {
+ // The conditions below must stay in sync with
TextFileInputMeta.getFields(), which adds
+ // these columns using StringUtils.isNotBlank(...). Using a plain !=
null check here would
+ // populate (and shift) columns that getFields never added when a
field name is set to an
+ // empty/blank string, misaligning every following additional output
field.
+ if
(StringUtils.isNotBlank(additionalOutputFields.getShortFilenameField())) {
r[index] = shortFilename;
index++;
}
// Add Extension
- if (additionalOutputFields.getExtensionField() != null) {
+ if
(StringUtils.isNotBlank(additionalOutputFields.getExtensionField())) {
r[index] = extension;
index++;
}
// add path
- if (additionalOutputFields.getPathField() != null) {
+ if (StringUtils.isNotBlank(additionalOutputFields.getPathField())) {
r[index] = path;
index++;
}
// Add Size
- if (additionalOutputFields.getSizeField() != null) {
+ if (StringUtils.isNotBlank(additionalOutputFields.getSizeField())) {
r[index] = size;
index++;
}
// add Hidden
- if (additionalOutputFields.getHiddenField() != null) {
+ if (StringUtils.isNotBlank(additionalOutputFields.getHiddenField())) {
r[index] = hidden;
index++;
}
// Add modification date
- if (additionalOutputFields.getLastModificationField() != null) {
+ if
(StringUtils.isNotBlank(additionalOutputFields.getLastModificationField())) {
r[index] = modificationDateTime;
index++;
}
// Add Uri
- if (additionalOutputFields.getUriField() != null) {
+ if (StringUtils.isNotBlank(additionalOutputFields.getUriField())) {
r[index] = uri;
index++;
}
// Add RootUri
- if (additionalOutputFields.getRootUriField() != null) {
+ if (StringUtils.isNotBlank(additionalOutputFields.getRootUriField())) {
r[index] = rooturi;
index++;
}
diff --git
a/plugins/transforms/textfile/src/test/java/org/apache/hop/pipeline/transforms/fileinput/text/TextFileInputContentParsingTest.java
b/plugins/transforms/textfile/src/test/java/org/apache/hop/pipeline/transforms/fileinput/text/TextFileInputContentParsingTest.java
index b716979ca4..6335105585 100644
---
a/plugins/transforms/textfile/src/test/java/org/apache/hop/pipeline/transforms/fileinput/text/TextFileInputContentParsingTest.java
+++
b/plugins/transforms/textfile/src/test/java/org/apache/hop/pipeline/transforms/fileinput/text/TextFileInputContentParsingTest.java
@@ -17,6 +17,10 @@
package org.apache.hop.pipeline.transforms.fileinput.text;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
import java.util.List;
import org.apache.hop.core.file.TextFileInputField;
import org.apache.hop.core.variables.Variables;
@@ -28,6 +32,97 @@ class TextFileInputContentParsingTest extends
BaseTextParsingTest {
@RegisterExtension
static RestoreHopEngineEnvironmentExtension env = new
RestoreHopEngineEnvironmentExtension();
+ /**
+ * Regression guard: the "Rownum in output" option must actually populate
the row-number column.
+ * It regressed (commit 6bdc5fd095) because
TextFileInputMeta.isIncludeRowNumber() was stubbed to
+ * return false, so getFields added the column but convertLineToRow never
filled it (null on every
+ * row).
+ */
+ @Test
+ void testIncludeRowNumberIsPopulated() throws Exception {
+ meta.getContent().setFileFormat("unix");
+ meta.getContent().setIncludeRowNumber(true);
+ meta.getContent().setRowNumberField("rownr");
+
+ initByFile("default.csv");
+ setFields(
+ new TextFileInputField("f1", -1, -1),
+ new TextFileInputField("f2", -1, -1),
+ new TextFileInputField("f3", -1, -1));
+
+ process();
+
+ int idx = data.outputRowMeta.indexOfValue("rownr");
+ assertTrue(idx >= 0, "rownr column should be present");
+ assertEquals(3, rows.size());
+ for (int i = 0; i < rows.size(); i++) {
+ assertNotNull(rows.get(i)[idx], "rownr must not be null on row " + i);
+ assertEquals((long) (i + 1), ((Number) rows.get(i)[idx]).longValue());
+ }
+ }
+
+ /**
+ * Regression guard for the "include filename in output" option, broken the
same way as rownum
+ * (TextFileInputMeta.isIncludeFilename() was stubbed to return false).
+ */
+ @Test
+ void testIncludeFilenameIsPopulated() throws Exception {
+ meta.getContent().setFileFormat("unix");
+ meta.getContent().setIncludeFilename(true);
+ meta.getContent().setFilenameField("fname");
+
+ initByFile("default.csv");
+ setFields(
+ new TextFileInputField("f1", -1, -1),
+ new TextFileInputField("f2", -1, -1),
+ new TextFileInputField("f3", -1, -1));
+
+ process();
+
+ int idx = data.outputRowMeta.indexOfValue("fname");
+ assertTrue(idx >= 0, "fname column should be present");
+ assertEquals(3, rows.size());
+ for (int i = 0; i < rows.size(); i++) {
+ Object value = rows.get(i)[idx];
+ assertNotNull(value, "filename must not be null on row " + i);
+ assertTrue(value.toString().endsWith("default.csv"), "unexpected
filename: " + value);
+ }
+ }
+
+ /**
+ * Regression guard for the additional-output-field misalignment: getFields
adds these columns
+ * with StringUtils.isNotBlank(...) but the runtime used to add/shift them
with a plain != null
+ * check. An empty-string field name (how the UI serializes an unused field)
would then be written
+ * by the runtime even though getFields skipped it, shifting every following
column by one. Here a
+ * blank short-filename field precedes a real extension field, so the
extension column must hold
+ * the file extension - not the misaligned short filename.
+ */
+ @Test
+ void testBlankAdditionalFieldDoesNotMisalignColumns() throws Exception {
+ meta.getContent().setFileFormat("unix");
+ // Unused field serialized as an empty string (not null), preceding a real
one.
+ meta.getAdditionalOutputFields().setShortFilenameField("");
+ meta.getAdditionalOutputFields().setExtensionField("theext");
+
+ initByFile("default.csv");
+ setFields(
+ new TextFileInputField("f1", -1, -1),
+ new TextFileInputField("f2", -1, -1),
+ new TextFileInputField("f3", -1, -1));
+
+ process();
+
+ // The blank short-filename field must NOT have produced a column.
+ assertTrue(
+ data.outputRowMeta.indexOfValue("") < 0, "a blank field name must not
create a column");
+ int idx = data.outputRowMeta.indexOfValue("theext");
+ assertTrue(idx >= 0, "extension column should be present");
+ assertEquals(3, rows.size());
+ for (int i = 0; i < rows.size(); i++) {
+ assertEquals("csv", rows.get(i)[idx], "extension column misaligned on
row " + i);
+ }
+ }
+
@Test
void testDefaultOptions() throws Exception {