Skip to content

Commit edbff87

Browse files
committed
Add unit tests for CapacityTableFunction to improve patch coverage
1 parent 7073de7 commit edbff87

1 file changed

Lines changed: 204 additions & 0 deletions

File tree

Lines changed: 204 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,204 @@
1+
/*
2+
* Licensed to the Apache Software Foundation (ASF) under one
3+
* or more contributor license agreements. See the NOTICE file
4+
* distributed with this work for additional information
5+
* regarding copyright ownership. The ASF licenses this file
6+
* to you under the Apache License, Version 2.0 (the
7+
* "License"); you may not use this file except in compliance
8+
* with the License. You may obtain a copy of the License at
9+
*
10+
* http://www.apache.org/licenses/LICENSE-2.0
11+
*
12+
* Unless required by applicable law or agreed to in writing,
13+
* software distributed under the License is distributed on an
14+
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15+
* KIND, either express or implied. See the License for the
16+
* specific language governing permissions and limitations
17+
* under the License.
18+
*/
19+
20+
package org.apache.iotdb.commons.udf.builtin.relational.tvf;
21+
22+
import org.apache.iotdb.udf.api.exception.UDFException;
23+
import org.apache.iotdb.udf.api.relational.access.Record;
24+
import org.apache.iotdb.udf.api.relational.table.TableFunctionAnalysis;
25+
import org.apache.iotdb.udf.api.relational.table.TableFunctionHandle;
26+
import org.apache.iotdb.udf.api.relational.table.TableFunctionProcessorProvider;
27+
import org.apache.iotdb.udf.api.relational.table.argument.Argument;
28+
import org.apache.iotdb.udf.api.relational.table.argument.ScalarArgument;
29+
import org.apache.iotdb.udf.api.relational.table.processor.TableFunctionDataProcessor;
30+
import org.apache.iotdb.udf.api.type.Type;
31+
32+
import org.apache.tsfile.block.column.ColumnBuilder;
33+
import org.junit.Test;
34+
import org.mockito.ArgumentCaptor;
35+
import org.mockito.Mockito;
36+
37+
import java.util.ArrayList;
38+
import java.util.Collections;
39+
import java.util.HashMap;
40+
import java.util.List;
41+
import java.util.Map;
42+
43+
import static org.junit.Assert.assertEquals;
44+
import static org.junit.Assert.assertNotNull;
45+
46+
public class CapacityTableFunctionTest {
47+
48+
private final CapacityTableFunction function = new CapacityTableFunction();
49+
50+
// ======================== analyze() tests ========================
51+
52+
@Test
53+
public void testAnalyzeWithSlideDefault() throws UDFException {
54+
Map<String, Argument> args = new HashMap<>();
55+
args.put("SIZE", new ScalarArgument(Type.INT64, 5L));
56+
args.put("SLIDE", new ScalarArgument(Type.INT64, -1L));
57+
58+
TableFunctionAnalysis analysis = function.analyze(args);
59+
assertNotNull(analysis);
60+
}
61+
62+
@Test
63+
public void testAnalyzeWithExplicitSlide() throws UDFException {
64+
Map<String, Argument> args = new HashMap<>();
65+
args.put("SIZE", new ScalarArgument(Type.INT64, 4L));
66+
args.put("SLIDE", new ScalarArgument(Type.INT64, 2L));
67+
68+
TableFunctionAnalysis analysis = function.analyze(args);
69+
assertNotNull(analysis);
70+
}
71+
72+
@Test(expected = UDFException.class)
73+
public void testAnalyzeSizeZero() throws UDFException {
74+
Map<String, Argument> args = new HashMap<>();
75+
args.put("SIZE", new ScalarArgument(Type.INT64, 0L));
76+
args.put("SLIDE", new ScalarArgument(Type.INT64, -1L));
77+
78+
function.analyze(args);
79+
}
80+
81+
@Test(expected = UDFException.class)
82+
public void testAnalyzeSizeNegative() throws UDFException {
83+
Map<String, Argument> args = new HashMap<>();
84+
args.put("SIZE", new ScalarArgument(Type.INT64, -3L));
85+
args.put("SLIDE", new ScalarArgument(Type.INT64, -1L));
86+
87+
function.analyze(args);
88+
}
89+
90+
// ======================== processor tests ========================
91+
92+
/**
93+
* Helper: builds the processor from analyze() -> getProcessorProvider() chain, then feeds N rows
94+
* through process(). Returns captured (windowIndex, passThroughIndex) pairs.
95+
*/
96+
private List<long[]> runProcessor(long size, long slide, int rowCount) throws UDFException {
97+
Map<String, Argument> args = new HashMap<>();
98+
args.put("SIZE", new ScalarArgument(Type.INT64, size));
99+
args.put("SLIDE", new ScalarArgument(Type.INT64, slide == -1 ? -1L : slide));
100+
101+
TableFunctionAnalysis analysis = function.analyze(args);
102+
TableFunctionHandle handle = analysis.getTableFunctionHandle();
103+
104+
TableFunctionProcessorProvider provider = function.getProcessorProvider(handle);
105+
TableFunctionDataProcessor processor = provider.getDataProcessor();
106+
107+
Record mockRecord = Mockito.mock(Record.class);
108+
List<long[]> results = new ArrayList<>();
109+
110+
for (int i = 0; i < rowCount; i++) {
111+
ArgumentCaptor<Long> windowCaptor = ArgumentCaptor.forClass(Long.class);
112+
ArgumentCaptor<Long> indexCaptor = ArgumentCaptor.forClass(Long.class);
113+
114+
ColumnBuilder properBuilder = Mockito.mock(ColumnBuilder.class);
115+
ColumnBuilder passThroughBuilder = Mockito.mock(ColumnBuilder.class);
116+
117+
processor.process(mockRecord, Collections.singletonList(properBuilder), passThroughBuilder);
118+
119+
Mockito.verify(properBuilder, Mockito.atLeast(0)).writeLong(windowCaptor.capture());
120+
Mockito.verify(passThroughBuilder, Mockito.atLeast(0)).writeLong(indexCaptor.capture());
121+
122+
List<Long> windows = windowCaptor.getAllValues();
123+
List<Long> indices = indexCaptor.getAllValues();
124+
for (int j = 0; j < windows.size(); j++) {
125+
results.add(new long[] {windows.get(j), indices.get(j)});
126+
}
127+
}
128+
return results;
129+
}
130+
131+
@Test
132+
public void testSlideEqualsSize() throws UDFException {
133+
// SIZE=2, SLIDE=2 (non-overlapping), 5 rows
134+
// window0: rows 0,1; window1: rows 2,3; window2: row 4
135+
List<long[]> results = runProcessor(2, 2, 5);
136+
long[][] expected = {{0, 0}, {0, 1}, {1, 2}, {1, 3}, {2, 4}};
137+
assertResultsEqual(expected, results);
138+
}
139+
140+
@Test
141+
public void testSlideDefault() throws UDFException {
142+
// SIZE=2, SLIDE=-1 (defaults to SIZE=2), 5 rows — same as above
143+
List<long[]> results = runProcessor(2, -1, 5);
144+
long[][] expected = {{0, 0}, {0, 1}, {1, 2}, {1, 3}, {2, 4}};
145+
assertResultsEqual(expected, results);
146+
}
147+
148+
@Test
149+
public void testSlideLessThanSize() throws UDFException {
150+
// SIZE=2, SLIDE=1 (overlapping), 3 rows
151+
// row0: window 0
152+
// row1: window 0, 1
153+
// row2: window 1, 2
154+
List<long[]> results = runProcessor(2, 1, 3);
155+
long[][] expected = {{0, 0}, {0, 1}, {1, 1}, {1, 2}, {2, 2}};
156+
assertResultsEqual(expected, results);
157+
}
158+
159+
@Test
160+
public void testSlideGreaterThanSize() throws UDFException {
161+
// SIZE=2, SLIDE=3 (gap), 6 rows
162+
// window0: rows 0,1; row2: gap; window1: rows 3,4; row5: gap
163+
List<long[]> results = runProcessor(2, 3, 6);
164+
long[][] expected = {{0, 0}, {0, 1}, {1, 3}, {1, 4}};
165+
assertResultsEqual(expected, results);
166+
}
167+
168+
@Test
169+
public void testOverlappingLargeSize() throws UDFException {
170+
// SIZE=3, SLIDE=2 (overlapping), 3 rows
171+
// row0: window 0
172+
// row1: window 0
173+
// row2: window 0, 1
174+
List<long[]> results = runProcessor(3, 2, 3);
175+
long[][] expected = {{0, 0}, {0, 1}, {0, 2}, {1, 2}};
176+
assertResultsEqual(expected, results);
177+
}
178+
179+
@Test
180+
public void testSingleRow() throws UDFException {
181+
// SIZE=3, SLIDE=1, 1 row — row0 belongs to window 0 only
182+
List<long[]> results = runProcessor(3, 1, 1);
183+
long[][] expected = {{0, 0}};
184+
assertResultsEqual(expected, results);
185+
}
186+
187+
@Test
188+
public void testGetArgumentsSpecifications() {
189+
assertEquals(3, function.getArgumentsSpecifications().size());
190+
}
191+
192+
@Test
193+
public void testCreateTableFunctionHandle() {
194+
assertNotNull(function.createTableFunctionHandle());
195+
}
196+
197+
private void assertResultsEqual(long[][] expected, List<long[]> actual) {
198+
assertEquals("Result count mismatch", expected.length, actual.size());
199+
for (int i = 0; i < expected.length; i++) {
200+
assertEquals("Window index mismatch at position " + i, expected[i][0], actual.get(i)[0]);
201+
assertEquals("PassThrough index mismatch at position " + i, expected[i][1], actual.get(i)[1]);
202+
}
203+
}
204+
}

0 commit comments

Comments
 (0)