blob: 4bc2b79ecfbac87fb236400eea85fb4732ff34f5 [file] [log] [blame]
/*=============================================================================#
# Copyright (c) 2020 Stephan Wahlbrink and others.
#
# This program and the accompanying materials are made available under the
# terms of the Eclipse Public License 2.0 which is available at
# https://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0
# which is available at https://www.apache.org/licenses/LICENSE-2.0.
#
# SPDX-License-Identifier: EPL-2.0 OR Apache-2.0
#
# Contributors:
# Stephan Wahlbrink <sw@wahlbrink.eu> - initial API and implementation
#=============================================================================*/
package org.eclipse.statet.rj.data.impl;
import static org.junit.jupiter.api.Assertions.assertArrayEquals;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNull;
import static org.eclipse.statet.rj.data.impl.AbstractRStore.DEFAULT_LONG_DATA_SEGMENT_LENGTH;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Random;
import java.util.function.Function;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.MethodSource;
import org.eclipse.statet.jcommons.lang.NonNullByDefault;
import org.eclipse.statet.jcommons.lang.Nullable;
import org.eclipse.statet.rj.data.RFactorStore;
import org.eclipse.statet.rj.data.RObject;
import org.eclipse.statet.rj.data.RStore;
@NonNullByDefault
public abstract class RFactorStoreTest extends AbstractRStoreTest {
static class FactorCaseData extends CaseData<RFactorStore> {
final static Function<FactorCaseData, RFactorStore> REF_CONSTRUCTOR= new RFactor32StoreTest()::createStore;
final boolean ordered;
final int[] codes;
final String[] levels;
public FactorCaseData(final String label, final boolean ordered,
final int[] codes, final boolean[] nas, final String[] levels) {
super(label, nas);
assert (codes.length == this.length);
assert (nas.length == this.length);
this.ordered= ordered;
this.codes= codes;
this.levels= levels;
setReference(REF_CONSTRUCTOR.apply(this));
}
public FactorCaseData(final String label, final boolean ordered,
final int[] codes, final String[] levels) {
super(label, codes.length);
assert (codes.length == this.length);
this.ordered= ordered;
this.codes= codes;
this.levels= levels;
setReference(REF_CONSTRUCTOR.apply(this));
}
}
protected static final List<FactorCaseData> DEFAULT_DATA_SOURCES;
static {
final var datas= new ArrayList<FactorCaseData>();
datas.add(new FactorCaseData("empty-unordered", false, new int[0],
new String[0] ));
datas.add(new FactorCaseData("empty-unordered-AB", false, new int[0],
new String[] { "A", "B" } ));
datas.add(new FactorCaseData("empty-ordered", true, new int[0],
new String[0] ));
datas.add(new FactorCaseData("empty-ordered-AB", false, new int[0],
new String[] { "A", "B" } ));
datas.add(new FactorCaseData("single-unordered-1", false, new int[] { 1 },
new String[] { "A", } ));
datas.add(new FactorCaseData("single-ordered-1", true, new int[] { 1 },
new String[] { "A", } ));
datas.add(new FactorCaseData("single-unordered-2", false, new int[] { 2 },
new String[] { "A", "B" } ));
datas.add(new FactorCaseData("single-ordered-2", true, new int[] { 2 },
new String[] { "A", "B" } ));
datas.add(new FactorCaseData("single-NA", false, new int[] { 0 }, new boolean[] { true },
new String[0] ));
datas.add(new FactorCaseData("single-NA-AB", false, new int[] { 0 }, new boolean[] { true },
new String[] { "A", "B" }));
{ final int[] values= new int[0x0FF];
final boolean[] nas= new boolean[values.length];
final String[] levels= new String[] { "A", "B", "C", "D", "E" };
Arrays.fill(values, 1);
int i= 0;
values[i++]= 2;
nas[i++]= true;
nas[i++]= true;
nas[i++]= true;
values[i++]= 2;
values[i++]= 3;
values[i++]= 5;
datas.add(new FactorCaseData("special", false, values, nas, levels));
}
{ final Random rand= new Random(68465);
final int[] values= new int[100000];
final String[] levels= new String[100];
for (int i= 0; i < levels.length; i++) {
levels[i]= "F" + (i + 1);
}
for (int i= 0; i < values.length; i++) {
values[i]= rand.nextInt(99) + 1;
}
datas.add(new FactorCaseData("rand100000", false, values, levels));
}
if (isBigDataEnabled(4)) {
final Random rand= new Random(46);
final int[] values= new int[DEFAULT_LONG_DATA_SEGMENT_LENGTH * 2 + 13];
final boolean[] nas= new boolean[DEFAULT_LONG_DATA_SEGMENT_LENGTH * 2 + 13];
final String[] levels= new String[100];
for (int i= 0; i < levels.length; i++) {
levels[i]= "F" + (i + 1);
}
for (int i= 0; i < values.length; i++) {
values[i]= rand.nextInt(100);
if (values[i] == 0) {
nas[i]= true;
}
}
datas.add(new FactorCaseData("randMultiSeg", false, values, nas, levels));
}
DEFAULT_DATA_SOURCES= datas;
}
public RFactorStoreTest() {
}
public static List<FactorCaseData> provideCaseDatas() {
return new ArrayList<>(DEFAULT_DATA_SOURCES);
}
protected abstract RFactorStore createStore(final FactorCaseData data);
@ParameterizedTest
@MethodSource("provideCaseDatas")
public void getStoreType(final FactorCaseData data) {
final RFactorStore store= createStore(data);
assertEquals(RStore.FACTOR, store.getStoreType());
}
@ParameterizedTest
@MethodSource("provideCaseDatas")
public void getBaseVectorRClassName(final FactorCaseData data) {
final RFactorStore store= createStore(data);
final String expected= (data.ordered) ? RObject.CLASSNAME_ORDERED : RObject.CLASSNAME_FACTOR;
assertEquals(expected, store.getBaseVectorRClassName());
}
@ParameterizedTest
@MethodSource("provideCaseDatas")
public void isOrdered(final FactorCaseData data) {
final RFactorStore store= createStore(data);
assertEquals(data.ordered, store.isOrdered());
}
@ParameterizedTest
@MethodSource("provideCaseDatas")
public void length(final FactorCaseData data) {
final RFactorStore store= createStore(data);
checkLength(data, store);
}
@ParameterizedTest
@MethodSource("provideCaseDatas")
public void getLevels(final FactorCaseData data) {
final RFactorStore store= createStore(data);
assertEquals(data.levels.length, store.getLevelCount());
assertArrayEquals(data.levels, store.getLevels().toArray());
}
@ParameterizedTest
@MethodSource("provideCaseDatas")
public void isNA(final FactorCaseData data) {
final RFactorStore store= createStore(data);
checkIsNA(data, store);
}
@ParameterizedTest
@MethodSource("provideCaseDatas")
public void isMissing(final FactorCaseData data) {
final RFactorStore store= createStore(data);
checkIsMissingNonNum(data, store);
}
@ParameterizedTest
@MethodSource("provideCaseDatas")
@SuppressWarnings("boxing")
public void getLogi(final FactorCaseData data) {
final RFactorStore store= createStore(data);
for (int i= 0; i < data.length; i++) {
final int i0= i;
if (data.nas[i0]) {
// undefined
}
else {
final Boolean expected= Boolean.valueOf(data.codes[i0] != 0);
assertEquals(expected, store.getLogi(i0));
assertEquals(expected, store.getLogi((long)i0));
}
}
assertIndexOutOfBounds(data, store::getLogi, store::getLogi);
}
@ParameterizedTest
@MethodSource("provideCaseDatas")
public void getInt(final FactorCaseData data) {
final RFactorStore store= createStore(data);
for (int i= 0; i < data.length; i++) {
final int i0= i;
if (data.nas[i0]) {
// undefined
}
else {
final int expected= data.codes[i0];
assertEquals(expected, store.getInt(i0));
assertEquals(expected, store.getInt((long)i0));
}
}
assertIndexOutOfBounds(data, store::getInt, store::getInt);
}
@ParameterizedTest
@MethodSource("provideCaseDatas")
public void getNum(final FactorCaseData data) {
final RFactorStore store= createStore(data);
for (int i= 0; i < data.length; i++) {
final int i0= i;
if (data.nas[i0]) {
// undefined
}
else {
final double expected= data.codes[i0];
assertEquals(expected, store.getNum(i0));
assertEquals(expected, store.getNum((long)i0));
}
}
assertIndexOutOfBounds(data, store::getNum, store::getNum);
}
@ParameterizedTest
@MethodSource("provideCaseDatas")
public void getChar(final FactorCaseData data) {
final RFactorStore store= createStore(data);
for (int i= 0; i < data.length; i++) {
final int i0= i;
if (data.nas[i0]) {
// undefined
}
else {
final String expected= data.levels[data.codes[i0] - 1];
assertEquals(expected, store.getChar(i0));
assertEquals(expected, store.getChar((long)i0));
}
}
assertIndexOutOfBounds(data, store::getChar, store::getChar);
}
@ParameterizedTest
@MethodSource("provideCaseDatas")
public void getRaw(final FactorCaseData data) {
final RFactorStore store= createStore(data);
for (int i= 0; i < data.length; i++) {
final int i0= i;
if (data.nas[i0]) {
// undefined
}
else if (data.codes[i0] >= 0 && data.codes[i0] < 0xFF) {
final byte expected= (byte)(data.codes[i0] & 0xFF);
assertEquals(expected, store.getRaw(i0));
assertEquals(expected, store.getRaw((long)i0));
}
}
assertIndexOutOfBounds(data, store::getRaw, store::getRaw);
}
@ParameterizedTest
@MethodSource("provideCaseDatas")
public void get(final FactorCaseData data) {
final RFactorStore store= createStore(data);
for (int i= 0; i < data.length; i++) {
final int i0= i;
if (data.nas[i0]) {
assertNull(store.get(i0), storeDiffersAt(i0));
}
else {
final Integer expected= Integer.valueOf(data.codes[i0]);
assertEquals(expected, store.get(i0));
assertEquals(expected, store.get((long)i0));
}
}
assertIndexOutOfBounds(data, store::get, store::get);
}
@ParameterizedTest
@MethodSource("provideCaseDatas")
public void toArray(final FactorCaseData data) {
final RFactorStore store= createStore(data);
final @Nullable Integer[] array= store.toArray();
assertEquals(data.codes.length, array.length);
for (int i= 0; i < data.length; i++) {
final int i0= i;
if (data.nas[i0]) {
assertNull(store.get(i0), storeDiffersAt(i0));
}
else {
final Integer expected= Integer.valueOf(data.codes[i]);
assertEquals(expected, array[i], arrayDiffersAt(i));
}
}
}
@ParameterizedTest
@MethodSource("provideCaseDatas")
public void writeExternal(final FactorCaseData data) throws IOException {
final RFactorStore store= createStore(data);
if (store instanceof ExternalizableRStore) {
final byte[] ser= writeExternal(store);
assertArrayEquals(data.getExternalBytes(), ser);
}
}
}