blob: cb0a6a548b855311d9907a3862b649f824a29484 [file] [log] [blame]
/* ====================================================================
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.
==================================================================== */
package org.apache.poi.hssf.record.cf;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertTrue;
import java.util.Arrays;
import org.apache.poi.ss.util.CellRangeAddress;
import org.apache.poi.ss.util.CellRangeUtil;
import org.junit.jupiter.api.Test;
/**
* Tests CellRange operations.
*/
final class TestCellRange {
private static final CellRangeAddress biggest = createCR( 0, -1, 0,-1);
private static final CellRangeAddress tenthColumn = createCR( 0, -1,10,10);
private static final CellRangeAddress tenthRow = createCR(10, 10, 0,-1);
private static final CellRangeAddress box10x10 = createCR( 0, 10, 0,10);
private static final CellRangeAddress box9x9 = createCR( 0, 9, 0, 9);
private static final CellRangeAddress box10to20c = createCR( 0, 10,10,20);
private static final CellRangeAddress oneCell = createCR(10, 10,10,10);
private static final CellRangeAddress[] sampleRanges = {
biggest, tenthColumn, tenthRow, box10x10, box9x9, box10to20c, oneCell,
};
/** cross-reference of <tt>contains()</tt> operations for sampleRanges against itself */
private static final boolean [][] containsExpectedResults =
{
// biggest, tenthColumn, tenthRow, box10x10, box9x9, box10to20c, oneCell
/*biggest */ {true, true , true , true , true , true , true},
/*tenthColumn*/ {false, true , false, false, false, false, true},
/*tenthRow */ {false, false, true , false, false, false, true},
/*box10x10 */ {false, false, false, true , true , false, true},
/*box9x9 */ {false, false, false, false, true , false, false},
/*box10to20c */ {false, false, false, false, false, true , true},
/*oneCell */ {false, false, false, false, false, false, true},
} ;
/**
* @param lastRow pass -1 for max row index
* @param lastCol pass -1 for max col index
*/
private static CellRangeAddress createCR(int firstRow, int lastRow, int firstCol, int lastCol) {
// max row & max col limit as per BIFF8
return new CellRangeAddress(
firstRow,
lastRow == -1 ? 0xFFFF : lastRow,
firstCol,
lastCol == -1 ? 0x00FF : lastCol);
}
@Test
void testContainsMethod()
{
CellRangeAddress [] ranges = sampleRanges;
for(int i=0; i!=ranges.length;i++)
{
for(int j=0; j!=ranges.length;j++)
{
boolean expectedResult = containsExpectedResults[i][j];
assertEquals(expectedResult, CellRangeUtil.contains(ranges[i], ranges[j]), "("+i+","+j+"): ");
}
}
}
private static final CellRangeAddress col1 = createCR( 0, -1, 1,1);
private static final CellRangeAddress col2 = createCR( 0, -1, 2,2);
private static final CellRangeAddress row1 = createCR( 1, 1, 0,-1);
private static final CellRangeAddress row2 = createCR( 2, 2, 0,-1);
private static final CellRangeAddress box0 = createCR( 0, 2, 0,2);
private static final CellRangeAddress box1 = createCR( 0, 1, 0,1);
private static final CellRangeAddress box2 = createCR( 0, 1, 2,3);
private static final CellRangeAddress box3 = createCR( 2, 3, 0,1);
private static final CellRangeAddress box4 = createCR( 2, 3, 2,3);
private static final CellRangeAddress box5 = createCR( 1, 3, 1,3);
@Test
void testHasSharedBorderMethod() {
assertFalse(CellRangeUtil.hasExactSharedBorder(col1, col1));
assertFalse(CellRangeUtil.hasExactSharedBorder(col2, col2));
assertTrue(CellRangeUtil.hasExactSharedBorder(col1, col2));
assertTrue(CellRangeUtil.hasExactSharedBorder(col2, col1));
assertFalse(CellRangeUtil.hasExactSharedBorder(row1, row1));
assertFalse(CellRangeUtil.hasExactSharedBorder(row2, row2));
assertTrue(CellRangeUtil.hasExactSharedBorder(row1, row2));
assertTrue(CellRangeUtil.hasExactSharedBorder(row2, row1));
assertFalse(CellRangeUtil.hasExactSharedBorder(row1, col1));
assertFalse(CellRangeUtil.hasExactSharedBorder(row1, col2));
assertFalse(CellRangeUtil.hasExactSharedBorder(col1, row1));
assertFalse(CellRangeUtil.hasExactSharedBorder(col2, row1));
assertFalse(CellRangeUtil.hasExactSharedBorder(row2, col1));
assertFalse(CellRangeUtil.hasExactSharedBorder(row2, col2));
assertFalse(CellRangeUtil.hasExactSharedBorder(col1, row2));
assertFalse(CellRangeUtil.hasExactSharedBorder(col2, row2));
assertTrue(CellRangeUtil.hasExactSharedBorder(col2, col1));
assertFalse(CellRangeUtil.hasExactSharedBorder(box1, box1));
assertTrue(CellRangeUtil.hasExactSharedBorder(box1, box2));
assertTrue(CellRangeUtil.hasExactSharedBorder(box1, box3));
assertFalse(CellRangeUtil.hasExactSharedBorder(box1, box4));
assertTrue(CellRangeUtil.hasExactSharedBorder(box2, box1));
assertFalse(CellRangeUtil.hasExactSharedBorder(box2, box2));
assertFalse(CellRangeUtil.hasExactSharedBorder(box2, box3));
assertTrue(CellRangeUtil.hasExactSharedBorder(box2, box4));
assertTrue(CellRangeUtil.hasExactSharedBorder(box3, box1));
assertFalse(CellRangeUtil.hasExactSharedBorder(box3, box2));
assertFalse(CellRangeUtil.hasExactSharedBorder(box3, box3));
assertTrue(CellRangeUtil.hasExactSharedBorder(box3, box4));
assertFalse(CellRangeUtil.hasExactSharedBorder(box4, box1));
assertTrue(CellRangeUtil.hasExactSharedBorder(box4, box2));
assertTrue(CellRangeUtil.hasExactSharedBorder(box4, box3));
assertFalse(CellRangeUtil.hasExactSharedBorder(box4, box4));
}
@Test
void testIntersectMethod() {
assertEquals(CellRangeUtil.OVERLAP, CellRangeUtil.intersect(box0, box5));
assertEquals(CellRangeUtil.OVERLAP, CellRangeUtil.intersect(box5, box0));
assertEquals(CellRangeUtil.NO_INTERSECTION, CellRangeUtil.intersect(box1, box4));
assertEquals(CellRangeUtil.NO_INTERSECTION, CellRangeUtil.intersect(box4, box1));
assertEquals(CellRangeUtil.NO_INTERSECTION, CellRangeUtil.intersect(box2, box3));
assertEquals(CellRangeUtil.NO_INTERSECTION, CellRangeUtil.intersect(box3, box2));
assertEquals(CellRangeUtil.INSIDE, CellRangeUtil.intersect(box0, box1));
assertEquals(CellRangeUtil.INSIDE, CellRangeUtil.intersect(box0, box0));
assertEquals(CellRangeUtil.ENCLOSES, CellRangeUtil.intersect(box1, box0));
assertEquals(CellRangeUtil.INSIDE, CellRangeUtil.intersect(tenthColumn, oneCell));
assertEquals(CellRangeUtil.ENCLOSES, CellRangeUtil.intersect(oneCell, tenthColumn));
assertEquals(CellRangeUtil.OVERLAP, CellRangeUtil.intersect(tenthColumn, tenthRow));
assertEquals(CellRangeUtil.OVERLAP, CellRangeUtil.intersect(tenthRow, tenthColumn));
assertEquals(CellRangeUtil.INSIDE, CellRangeUtil.intersect(tenthColumn, tenthColumn));
assertEquals(CellRangeUtil.INSIDE, CellRangeUtil.intersect(tenthRow, tenthRow));
// Bug 55380
assertEquals(CellRangeUtil.OVERLAP, CellRangeUtil.intersect(
CellRangeAddress.valueOf("C1:D2"), CellRangeAddress.valueOf("C2:C3")));
}
/**
* Cell ranges like the following are valid
* =$C:$IV,$B$1:$B$8,$B$10:$B$65536,$A:$A
*/
@Test
void testCreate() {
CellRangeAddress cr = createCR(0, -1, 2, 255); // $C:$IV
assertFalse(cr.isFullRowRange(), "isFullRowRange");
assertTrue(cr.isFullColumnRange(), "isFullColumnRange");
createCR(0, 7, 1, 1); // $B$1:$B$8
// bug 44739 - invalid cell range
createCR(9, -1, 1, 1); // $B$65536
createCR(0, -1, 0, 0); // $A:$A
}
@Test
void testNumberOfCells() {
assertEquals(1, oneCell.getNumberOfCells());
assertEquals(100, box9x9.getNumberOfCells());
assertEquals(121, box10to20c.getNumberOfCells());
}
@SuppressWarnings("RedundantArrayCreation")
@Test
void testMergeCellRanges() {
// no result on empty
cellRangeTest(new String[]{ });
// various cases with two ranges
cellRangeTest(new String[]{"A1:B1", "A2:B2"}, "A1:B2");
cellRangeTest(new String[]{"A1:B1" }, "A1:B1");
cellRangeTest(new String[]{"A1:B2", "A2:B2"}, "A1:B2");
cellRangeTest(new String[]{"A1:B3", "A2:B2"}, "A1:B3");
cellRangeTest(new String[]{"A1:C1", "A2:B2"}, new String[] {"A1:C1", "A2:B2"});
// cases with three ranges
cellRangeTest(new String[]{"A1:A1", "A2:B2", "A1:C1"}, new String[] {"A1:C1", "A2:B2"});
cellRangeTest(new String[]{"A1:C1", "A2:B2", "A1:A1"}, new String[] {"A1:C1", "A2:B2"});
// "standard" cases
// enclose
cellRangeTest(new String[]{"A1:D4", "B2:C3"}, new String[] {"A1:D4"});
// inside
cellRangeTest(new String[]{"B2:C3", "A1:D4"}, new String[] {"A1:D4"});
cellRangeTest(new String[]{"B2:C3", "A1:D4"}, new String[] {"A1:D4"});
// disjunct
cellRangeTest(new String[]{"A1:B2", "C3:D4"}, new String[] {"A1:B2", "C3:D4"});
cellRangeTest(new String[]{"A1:B2", "A3:D4"}, new String[] {"A1:B2", "A3:D4"});
// overlap that cannot be merged
cellRangeTest(new String[]{"C1:D2", "C2:C3"}, new String[] {"C1:D2", "C2:C3"});
// overlap which could theoretically be merged, but isn't because the implementation was buggy and therefore was removed
cellRangeTest(new String[]{"A1:C3", "B1:D3"}, new String[] {"A1:C3", "B1:D3"}); // could be one region "A1:D3"
cellRangeTest(new String[]{"A1:C3", "B1:D1"}, new String[] {"A1:C3", "B1:D1"}); // could be one region "A1:D3"
}
@SuppressWarnings("RedundantArrayCreation")
@Test
void testMergeCellRanges55380() {
cellRangeTest(new String[]{"C1:D2", "C2:C3"}, new String[] {"C1:D2", "C2:C3"});
cellRangeTest(new String[]{"A1:C3", "B2:D2"}, new String[] {"A1:C3", "B2:D2"});
cellRangeTest(new String[]{"C9:D30", "C7:C31"}, new String[] {"C9:D30", "C7:C31"});
}
// void testResolveRangeOverlap() {
// resolveRangeOverlapTest("C1:D2", "C2:C3");
// }
private void cellRangeTest(String[] input, String... expectedOutput) {
CellRangeAddress[] inputArr = new CellRangeAddress[input.length];
for(int i = 0;i < input.length;i++) {
inputArr[i] = CellRangeAddress.valueOf(input[i]);
}
CellRangeAddress[] result = CellRangeUtil.mergeCellRanges(inputArr);
verifyExpectedResult(result, expectedOutput);
}
// private void resolveRangeOverlapTest(String a, String b, String...expectedOutput) {
// CellRangeAddress rangeA = CellRangeAddress.valueOf(a);
// CellRangeAddress rangeB = CellRangeAddress.valueOf(b);
// CellRangeAddress[] result = CellRangeUtil.resolveRangeOverlap(rangeA, rangeB);
// verifyExpectedResult(result, expectedOutput);
// }
private void verifyExpectedResult(CellRangeAddress[] result, String... expectedOutput) {
assertEquals(expectedOutput.length, result.length,
"\nExpected: " + Arrays.toString(expectedOutput) + "\nHad: " + Arrays.toString(result));
for(int i = 0;i < expectedOutput.length;i++) {
assertEquals(expectedOutput[i], result[i].formatAsString(),
"\nExpected: " + Arrays.toString(expectedOutput) + "\nHad: " + Arrays.toString(result));
}
}
@Test
void testValueOf() {
CellRangeAddress cr1 = CellRangeAddress.valueOf("A1:B1");
assertEquals(0, cr1.getFirstColumn());
assertEquals(0, cr1.getFirstRow());
assertEquals(1, cr1.getLastColumn());
assertEquals(0, cr1.getLastRow());
CellRangeAddress cr2 = CellRangeAddress.valueOf("B1");
assertEquals(1, cr2.getFirstColumn());
assertEquals(0, cr2.getFirstRow());
assertEquals(1, cr2.getLastColumn());
assertEquals(0, cr2.getLastRow());
}
}