diff --git a/common/src/test/java/org/eclipse/daanse/olap/calc/base/type/tuplebase/TupleListTest.java b/common/src/test/java/org/eclipse/daanse/olap/calc/base/type/tuplebase/TupleListTest.java new file mode 100644 index 00000000..c97db3ea --- /dev/null +++ b/common/src/test/java/org/eclipse/daanse/olap/calc/base/type/tuplebase/TupleListTest.java @@ -0,0 +1,44 @@ +/* + * This software is subject to the terms of the Eclipse Public License v1.0 + * Agreement, available at the following URL: + * http://www.eclipse.org/legal/epl-v10.html. + * You must accept the terms of that agreement to use this software. + * + * Copyright (C) 2002-2017 Hitachi Vantara and others + * All Rights Reserved. + * + * ---- All changes after Fork in 2023 ------------------------ + * + * Project: Eclipse daanse + * + * Copyright (c) 2023 Contributors to the Eclipse Foundation. + * + * 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/ + * + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors after Fork in 2023: + * SmartCity Jena - initial + */ +package org.eclipse.daanse.olap.calc.base.type.tuplebase; + +import static org.junit.jupiter.api.Assertions.assertTrue; + +import org.eclipse.daanse.olap.api.calc.todo.TupleList; +import org.junit.jupiter.api.Test; + +/** + * Unit test for {@link TupleList} and common implementations. + * + * @author jhyde + */ +class TupleListTest { + + @Test + void testTupleList() { + assertTrue(TupleCollections.createList(1) instanceof UnaryTupleList); + assertTrue(TupleCollections.createList(2) instanceof ArrayTupleList); + } +} diff --git a/common/src/test/java/org/eclipse/daanse/olap/fun/SortTest.java b/common/src/test/java/org/eclipse/daanse/olap/fun/SortTest.java new file mode 100644 index 00000000..0e7e2ea1 --- /dev/null +++ b/common/src/test/java/org/eclipse/daanse/olap/fun/SortTest.java @@ -0,0 +1,81 @@ +/* + * This software is subject to the terms of the Eclipse Public License v1.0 + * Agreement, available at the following URL: + * http://www.eclipse.org/legal/epl-v10.html. + * You must accept the terms of that agreement to use this software. + * + * Copyright (c) 2002-2020 Hitachi Vantara.. All rights reserved. + * + * ---- All changes after Fork in 2023 ------------------------ + * + * Project: Eclipse daanse + * + * Copyright (c) 2023 Contributors to the Eclipse Foundation. + * + * 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/ + * + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors after Fork in 2023: + * SmartCity Jena - initial + */ +package org.eclipse.daanse.olap.fun; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +import org.eclipse.daanse.olap.common.SystemWideProperties; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.Test; + + +/** + * SortTest tests the collation order of positive and negative + * infinity, and {@link Double#NaN}. + * + * @author jhyde + * @since Sep 21, 2006 + */ +class SortTest { + + /** + * Access properties via this object and their values will be reset. + */ + + @AfterEach + public void afterEach() { + SystemWideProperties.instance().populateInitial(); + } + + @Test + void testFoo() { + // Check that each value compares according to its position in the total + // order. For example, NaN compares greater than + // Double.NEGATIVE_INFINITY, -34.5, -0.001, 0, 0.00000567, 1, 3.14; + // equal to NaN; and less than Double.POSITIVE_INFINITY. + double[] values = { + Double.NEGATIVE_INFINITY, + FunUtil.DOUBLE_NULL, + -34.5, + -0.001, + 0, + 0.00000567, + 1, + 3.14, + Double.NaN, + Double.POSITIVE_INFINITY, + }; + for ( int i = 0; i < values.length; i++ ) { + for ( int j = 0; j < values.length; j++ ) { + int expected = Integer.compare( i, j ); + assertEquals( + expected, + FunUtil.compareValues( values[ i ], values[ j ] ), + "values[" + i + "]=" + values[ i ] + ", values[" + j + + "]=" + values[ j ]); + } + } + } + +} diff --git a/common/src/test/java/org/eclipse/daanse/olap/function/def/crossjoin/CrossJoinTest.java b/common/src/test/java/org/eclipse/daanse/olap/function/def/crossjoin/CrossJoinTest.java new file mode 100644 index 00000000..8009c23a --- /dev/null +++ b/common/src/test/java/org/eclipse/daanse/olap/function/def/crossjoin/CrossJoinTest.java @@ -0,0 +1,501 @@ +/* + * This software is subject to the terms of the Eclipse Public License v1.0 + * Agreement, available at the following URL: + * http://www.eclipse.org/legal/epl-v10.html. + * You must accept the terms of that agreement to use this software. + * + * Copyright (c) 2002-2020 Hitachi Vantara.. All rights reserved. + * ---- All changes after Fork in 2023 ------------------------ + * + * Project: Eclipse daanse + * + * Copyright (c) 2023 Contributors to the Eclipse Foundation. + * + * 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/ + * + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors after Fork in 2023: + * SmartCity Jena - initial + */ + +package org.eclipse.daanse.olap.function.def.crossjoin; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +import java.io.PrintWriter; +import java.util.Arrays; +import java.util.Collections; +import java.util.Comparator; +import java.util.List; + +import org.eclipse.daanse.mdx.model.api.expression.operation.FunctionOperationAtom; +import org.eclipse.daanse.mdx.model.api.expression.operation.OperationAtom; +import org.eclipse.daanse.olap.api.ConfigConstants; +import org.eclipse.daanse.olap.api.Context; +import org.eclipse.daanse.olap.api.DataType; +import org.eclipse.daanse.olap.api.Statement; +import org.eclipse.daanse.olap.api.Validator; +import org.eclipse.daanse.olap.api.calc.Calc; +import org.eclipse.daanse.olap.api.calc.compiler.ExpressionCompiler; +import org.eclipse.daanse.olap.api.calc.todo.TupleCursor; +import org.eclipse.daanse.olap.api.calc.todo.TupleIterable; +import org.eclipse.daanse.olap.api.calc.todo.TupleList; +import org.eclipse.daanse.olap.api.connection.Connection; +import org.eclipse.daanse.olap.api.element.Member; +import org.eclipse.daanse.olap.api.function.FunctionDefinition; +import org.eclipse.daanse.olap.api.function.FunctionMetaData; +import org.eclipse.daanse.olap.api.function.FunctionParameter; +import org.eclipse.daanse.olap.api.query.component.Expression; +import org.eclipse.daanse.olap.api.query.component.ResolvedFunCall; +import org.eclipse.daanse.olap.api.result.Position; +import org.eclipse.daanse.olap.api.result.Result; +import org.eclipse.daanse.olap.api.type.MemberType; +import org.eclipse.daanse.olap.api.type.SetType; +import org.eclipse.daanse.olap.api.type.TupleType; +import org.eclipse.daanse.olap.api.type.Type; +import org.eclipse.daanse.olap.calc.base.type.tuplebase.ArrayTupleList; +import org.eclipse.daanse.olap.calc.base.type.tuplebase.UnaryTupleList; +import org.eclipse.daanse.olap.common.SystemWideProperties; +import org.eclipse.daanse.olap.function.core.FunctionParameterR; +import org.eclipse.daanse.olap.query.component.ResolvedFunCallImpl; +import org.eclipse.daanse.olap.server.ExecutionImpl; +import org.eclipse.daanse.olap.server.LocusImpl; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + + +/** + * CrossJoint tests the collation order of positive and negative + * infinity, and {@link Double#NaN}. + * + * @author Richard M. Emberson + * @since Jan 14, 2007 + */ + +public class CrossJoinTest { + + private static final String SELECT_GENDER_MEMBERS = + "select Gender.members on 0 from sales"; + + private static final String SALES_CUBE = "Sales"; + + private ExecutionImpl excMock = mock( ExecutionImpl.class ); + + static List> m3 = Arrays.asList( + Arrays.asList( new TestMember( "k" ), new TestMember( "l" ) ), + Arrays.asList( new TestMember( "m" ), new TestMember( "n" ) ) ); + + static List> m4 = Arrays.asList( + Arrays.asList( new TestMember( "U" ), new TestMember( "V" ) ), + Arrays.asList( new TestMember( "W" ), new TestMember( "X" ) ), + Arrays.asList( new TestMember( "Y" ), new TestMember( "Z" ) ) ); + + static final Comparator> memberComparator = + new Comparator<>() { + @Override + public int compare( List ma1, List ma2 ) { + for ( int i = 0; i < ma1.size(); i++ ) { + int c = ma1.get( i ).compareTo( ma2.get( i ) ); + if ( c < 0 ) { + return c; + } else if ( c > 0 ) { + return c; + } + } + return 0; + } + }; + + private CrossJoinFunDef crossJoinFunDef; + + @BeforeEach + protected void beforeEach() throws Exception { + crossJoinFunDef = new CrossJoinFunDef( new NullFunDef().getFunctionMetaData() ); + } + + @AfterEach + protected void afterEach() throws Exception { + SystemWideProperties.instance().populateInitial(); + } + + //////////////////////////////////////////////////////////////////////// + // Iterable + //////////////////////////////////////////////////////////////////////// + + @Test + void testListTupleListTupleIterCalc() { + Statement statement = mock(Statement.class); + Connection rolapConnection = mock(Connection.class); + Context context = mock(Context.class); + when(context.getConfigValue(ConfigConstants.CHECK_CANCEL_OR_TIMEOUT_INTERVAL, ConfigConstants.CHECK_CANCEL_OR_TIMEOUT_INTERVAL_DEFAULT_VALUE, Integer.class)).thenReturn(0); + when(rolapConnection.getContext()).thenReturn(context); + when(statement.getMondrianConnection()).thenReturn(rolapConnection); + when(excMock.getMondrianStatement()).thenReturn(statement); + CrossJoinIterCalc calc = + new CrossJoinIterCalc( getResolvedFunCall(), null, crossJoinFunDef.getCtag() ); + + doTupleTupleIterTest( calc, excMock ); + } + + private void doTupleTupleIterTest( + CrossJoinIterCalc calc, ExecutionImpl execution ) { + TupleList l4 = makeListTuple( m4 ); + String s4 = toString( l4 ); + String e4 = "{[U, V], [W, X], [Y, Z]}"; + assertEquals( e4, s4 ); + + TupleList l3 = makeListTuple( m3 ); + String s3 = toString( l3 ); + String e3 = "{[k, l], [m, n]}"; + assertEquals( e3, s3 ); + + String s = LocusImpl.execute( + execution, "CrossJoinTest", new LocusImpl.Action() { + @Override + public String execute() { + TupleIterable iterable = calc.makeIterable( l4, l3 ); + return CrossJoinTest.this.toString( iterable ); + } + } ); + String e = + "{[U, V, k, l], [U, V, m, n], [W, X, k, l], " + + "[W, X, m, n], [Y, Z, k, l], [Y, Z, m, n]}"; + assertEquals( e, s ); + } + + + private static TupleList getGenderMembers( Result genders ) { + TupleList genderMembers = new UnaryTupleList(); + for ( Position pos : genders.getAxes()[ 0 ].getPositions() ) { + genderMembers.add( pos ); + } + return genderMembers; + } + + private Integer crossJoinIterCalcIterate( + final TupleList list1, final TupleList list2, + final ExecutionImpl execution ) { + return LocusImpl.execute( + execution, "CrossJoinTest", new LocusImpl.Action() { + @Override + public Integer execute() { + TupleIterable iterable = + new CrossJoinIterCalc( + getResolvedFunCall(), null, crossJoinFunDef.getCtag() ).makeIterable( list1, list2 ); + TupleCursor tupleCursor = iterable.tupleCursor(); + // total count of all iterations + int counter = 0; + while ( tupleCursor.forward() ) { + counter++; + } + return Integer.valueOf( counter ); + } + } ); + } + + //////////////////////////////////////////////////////////////////////// + // Immutable List + //////////////////////////////////////////////////////////////////////// + + @Test + void testImmutableListTupleListTupleListCalc() { + ImmutableListCalc calc = + new ImmutableListCalc( + getResolvedFunCall(), null, crossJoinFunDef.getCtag() ); + + doTupleTupleListTest( calc ); + } + + protected void doTupleTupleListTest( + BaseListCalc calc ) { + TupleList l4 = makeListTuple( m4 ); + String s4 = toString( l4 ); + String e4 = "{[U, V], [W, X], [Y, Z]}"; + assertEquals( e4, s4 ); + + TupleList l3 = makeListTuple( m3 ); + String s3 = toString( l3 ); + String e3 = "{[k, l], [m, n]}"; + assertEquals( e3, s3 ); + + TupleList list = calc.makeList( l4, l3 ); + String s = toString( list ); + String e = + "{[U, V, k, l], [U, V, m, n], [W, X, k, l], " + + "[W, X, m, n], [Y, Z, k, l], [Y, Z, m, n]}"; + assertEquals( e, s ); + + TupleList subList = list.subList( 0, 6 ); + s = toString( subList ); + assertEquals( 6, subList.size() ); + assertEquals( e, s ); + + subList = subList.subList( 0, 6 ); + s = toString( subList ); + assertEquals( 6, subList.size() ); + assertEquals( e, s ); + + subList = subList.subList( 1, 5 ); + s = toString( subList ); + e = "{[U, V, m, n], [W, X, k, l], [W, X, m, n], [Y, Z, k, l]}"; + assertEquals( 4, subList.size() ); + assertEquals( e, s ); + + subList = subList.subList( 2, 4 ); + s = toString( subList ); + e = "{[W, X, m, n], [Y, Z, k, l]}"; + assertEquals( 2, subList.size() ); + assertEquals( e, s ); + + subList = subList.subList( 1, 2 ); + s = toString( subList ); + e = "{[Y, Z, k, l]}"; + assertEquals( 1, subList.size() ); + assertEquals( e, s ); + + subList = list.subList( 1, 4 ); + s = toString( subList ); + e = "{[U, V, m, n], [W, X, k, l], [W, X, m, n]}"; + assertEquals( 3, subList.size() ); + assertEquals( e, s ); + + subList = list.subList( 2, 4 ); + s = toString( subList ); + e = "{[W, X, k, l], [W, X, m, n]}"; + assertEquals( 2, subList.size() ); + assertEquals( e, s ); + + subList = list.subList( 2, 3 ); + s = toString( subList ); + e = "{[W, X, k, l]}"; + assertEquals( 1, subList.size() ); + assertEquals( e, s ); + + subList = list.subList( 4, 4 ); + s = toString( subList ); + e = "{}"; + assertEquals( 0, subList.size() ); + assertEquals( e, s ); + } + + + //////////////////////////////////////////////////////////////////////// + // Mutable List + //////////////////////////////////////////////////////////////////////// + @Test + void testMutableListTupleListTupleListCalc() { + MutableListCalc calc = + new MutableListCalc( + getResolvedFunCall(), null, crossJoinFunDef.getCtag() ); + + doMTupleTupleListTest( calc ); + } + + protected void doMTupleTupleListTest( + BaseListCalc calc ) { + TupleList l1 = makeListTuple( m3 ); + String s1 = toString( l1 ); + String e1 = "{[k, l], [m, n]}"; + assertEquals( e1, s1 ); + + TupleList l2 = makeListTuple( m4 ); + String s2 = toString( l2 ); + String e2 = "{[U, V], [W, X], [Y, Z]}"; + assertEquals( e2, s2 ); + + TupleList list = calc.makeList( l1, l2 ); + String s = toString( list ); + String e = "{[k, l, U, V], [k, l, W, X], [k, l, Y, Z], " + + "[m, n, U, V], [m, n, W, X], [m, n, Y, Z]}"; + assertEquals( e, s ); + + if ( false ) { + // Cannot apply Collections.reverse to TupleList + // because TupleList.set always returns null. + // (This is a violation of the List contract, but it is inefficient + // to construct a list to return.) + Collections.reverse( list ); + s = toString( list ); + e = "{[m, n, Y, Z], [m, n, W, X], [m, n, U, V], " + + "[k, l, Y, Z], [k, l, W, X], [k, l, U, V]}"; + assertEquals( e, s ); + } + + // sort + Collections.sort( list, memberComparator ); + s = toString( list ); + e = "{[k, l, U, V], [k, l, W, X], [k, l, Y, Z], " + + "[m, n, U, V], [m, n, W, X], [m, n, Y, Z]}"; + assertEquals( e, s ); + + List members = list.remove( 1 ); + s = toString( list ); + e = "{[k, l, U, V], [k, l, Y, Z], [m, n, U, V], " + + "[m, n, W, X], [m, n, Y, Z]}"; + assertEquals( e, s ); + } + + //////////////////////////////////////////////////////////////////////// + // Helper methods + //////////////////////////////////////////////////////////////////////// + protected String toString( TupleIterable l ) { + StringBuffer buf = new StringBuffer( 100 ); + buf.append( '{' ); + int j = 0; + for ( List o : l ) { + if ( j++ > 0 ) { + buf.append( ", " ); + } + buf.append( o ); + } + buf.append( '}' ); + return buf.toString(); + } + + protected TupleList makeListTuple( List> ms ) { + final TupleList list = new ArrayTupleList( ms.get( 0 ).size() ); + for ( List m : ms ) { + list.add( m ); + } + return list; + } + + protected ResolvedFunCallImpl getResolvedFunCall() { + FunctionDefinition funDef = new TestFunDef(); + Expression[] args = new Expression[ 0 ]; + Type returnType = + new SetType( + new TupleType( + new Type[] { + new MemberType( null, null, null, null ), + new MemberType( null, null, null, null ) } ) ); + return new ResolvedFunCallImpl( funDef, args, returnType ); + } + + //////////////////////////////////////////////////////////////////////// + // Helper classes + //////////////////////////////////////////////////////////////////////// + public static class TestFunDef implements FunctionDefinition { + TestFunDef() { + } + + + @Override + public Expression createCall( Validator validator, Expression[] args ) { + throw new UnsupportedOperationException(); + } + + @Override + public String getSignature() { + throw new UnsupportedOperationException(); + } + + @Override + public void unparse( Expression[] args, PrintWriter pw ) { + throw new UnsupportedOperationException(); + } + + @Override + public Calc compileCall( ResolvedFunCall call, ExpressionCompiler compiler ) { + throw new UnsupportedOperationException(); + } + + @Override + public FunctionMetaData getFunctionMetaData() { + return new FunctionMetaData() { + + @Override + public OperationAtom operationAtom() { + + return new FunctionOperationAtom("SomeName"); + } + + @Override + public String description() { + throw new UnsupportedOperationException(); + } + + @Override + public DataType returnCategory() { + throw new UnsupportedOperationException(); + } + + @Override + public DataType[] parameterDataTypes() { + throw new UnsupportedOperationException(); + } + + + @Override + public FunctionParameterR[] parameters() { + throw new UnsupportedOperationException(); + } + + }; + } + } + + public static class NullFunDef implements FunctionDefinition { + public NullFunDef() { + } + + + + @Override + public Expression createCall( Validator validator, Expression[] args ) { + return null; + } + + @Override + public String getSignature() { + return ""; + } + + @Override + public void unparse( Expression[] args, PrintWriter pw ) { + // + } + + @Override + public Calc compileCall( ResolvedFunCall call, ExpressionCompiler compiler ) { + return null; + } + + @Override + public FunctionMetaData getFunctionMetaData() { + return new FunctionMetaData() { + + @Override + public OperationAtom operationAtom() { + return new FunctionOperationAtom(""); + } + + @Override + public String description() { + return ""; + } + + @Override + public DataType returnCategory() { + return DataType.UNKNOWN; + } + + @Override + public DataType[] parameterDataTypes() { + return new DataType[ 0 ]; + } + + @Override + public FunctionParameter[] parameters() { + return new FunctionParameter[0]; + } + }; + } + } +} diff --git a/common/src/test/java/org/eclipse/daanse/olap/function/def/crossjoin/TestMember.java b/common/src/test/java/org/eclipse/daanse/olap/function/def/crossjoin/TestMember.java new file mode 100644 index 00000000..9fff7269 --- /dev/null +++ b/common/src/test/java/org/eclipse/daanse/olap/function/def/crossjoin/TestMember.java @@ -0,0 +1,349 @@ +/* + * This software is subject to the terms of the Eclipse Public License v1.0 + * Agreement, available at the following URL: + * http://www.eclipse.org/legal/epl-v10.html. + * You must accept the terms of that agreement to use this software. + * + * Copyright (c) 2002-2020 Hitachi Vantara.. All rights reserved. + * + * ---- All changes after Fork in 2023 ------------------------ + * + * Project: Eclipse daanse + * + * Copyright (c) 2023 Contributors to the Eclipse Foundation. + * + * 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/ + * + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors after Fork in 2023: + * SmartCity Jena - initial + */ +package org.eclipse.daanse.olap.function.def.crossjoin; + +import java.util.List; +import java.util.Locale; + +import org.eclipse.daanse.olap.api.MatchType; +import org.eclipse.daanse.olap.api.CatalogReader; +import org.eclipse.daanse.olap.api.Segment; +import org.eclipse.daanse.olap.api.element.Dimension; +import org.eclipse.daanse.olap.api.element.DimensionType; +import org.eclipse.daanse.olap.api.element.Hierarchy; +import org.eclipse.daanse.olap.api.element.Level; +import org.eclipse.daanse.olap.api.element.Member; +import org.eclipse.daanse.olap.api.element.MetaData; +import org.eclipse.daanse.olap.api.element.OlapElement; +import org.eclipse.daanse.olap.api.element.Catalog; +import org.eclipse.daanse.olap.api.element.Cube; +import org.eclipse.daanse.olap.api.query.component.Expression; +import org.eclipse.daanse.olap.element.AbstractProperty; + +/** + * Mock implementation of {@link Member} for testing. + * + * @author Richard M. Emberson + */ +public class TestMember implements Member { + private final String identifer; + + public TestMember( String identifer ) { + this.identifer = identifer; + } + + @Override +public String toString() { + return identifer; + } + + @Override +public int compareTo( Object o ) { + TestMember other = (TestMember) o; + return this.identifer.compareTo( other.identifer ); + } + + @Override +public Member getParentMember() { + throw new UnsupportedOperationException(); + } + + @Override +public Level getLevel() { + throw new UnsupportedOperationException(); + } + + @Override +public Hierarchy getHierarchy() { + throw new UnsupportedOperationException(); + } + + @Override +public String getParentUniqueName() { + throw new UnsupportedOperationException(); + } + + @Override +public MemberType getMemberType() { + throw new UnsupportedOperationException(); + } + + @Override +public boolean isParentChildLeaf() { + return false; + } + + @Override +public boolean isParentChildPhysicalMember() { + return false; + } + + @Override +public void setName( String name ) { + throw new UnsupportedOperationException(); + } + + @Override +public boolean isAll() { + return false; + } + + @Override +public boolean isMeasure() { + throw new UnsupportedOperationException(); + } + + @Override +public boolean isNull() { + return true; + } + + @Override +public boolean isChildOrEqualTo( Member member ) { + throw new UnsupportedOperationException(); + } + + @Override +public boolean isCalculated() { + throw new UnsupportedOperationException(); + } + + @Override +public boolean isEvaluated() { + throw new UnsupportedOperationException(); + } + + @Override +public int getSolveOrder() { + throw new UnsupportedOperationException(); + } + + @Override +public Expression getExpression() { + throw new UnsupportedOperationException(); + } + + @Override +public List getAncestorMembers() { + throw new UnsupportedOperationException(); + } + + @Override +public boolean isCalculatedInQuery() { + throw new UnsupportedOperationException(); + } + + @Override +public Object getPropertyValue( String propertyName ) { + throw new UnsupportedOperationException(); + } + + @Override +public Object getPropertyValue( String propertyName, boolean matchCase ) { + throw new UnsupportedOperationException(); + } + + @Override +public String getPropertyFormattedValue( String propertyName ) { + throw new UnsupportedOperationException(); + } + + @Override +public void setProperty( String name, Object value ) { + throw new UnsupportedOperationException(); + } + + @Override +public AbstractProperty[] getProperties() { + throw new UnsupportedOperationException(); + } + + @Override +public int getOrdinal() { + throw new UnsupportedOperationException(); + } + + @Override +public Comparable getOrderKey() { + throw new UnsupportedOperationException(); + } + + @Override +public boolean isHidden() { + throw new UnsupportedOperationException(); + } + + @Override +public int getDepth() { + throw new UnsupportedOperationException(); + } + + @Override +public Member getDataMember() { + throw new UnsupportedOperationException(); + } + + @Override public boolean isOnSameHierarchyChain( Member otherMember ) { + throw new UnsupportedOperationException(); + } + + @Override +public String getUniqueName() { + throw new UnsupportedOperationException(); + } + + @Override +public String getName() { + throw new UnsupportedOperationException(); + } + + @Override +public String getDescription() { + throw new UnsupportedOperationException(); + } + + @Override +public OlapElement lookupChild( + CatalogReader schemaReader, Segment s, MatchType matchType ) { + throw new UnsupportedOperationException(); + } + + @Override +public String getQualifiedName() { + throw new UnsupportedOperationException(); + } + + @Override +public String getCaption() { + throw new UnsupportedOperationException(); + } + + @Override +public String getLocalized( LocalizedProperty prop, Locale locale ) { + throw new UnsupportedOperationException(); + } + + @Override +public boolean isVisible() { + throw new UnsupportedOperationException(); + } + + @Override +public Dimension getDimension() { + return new MockDimension(); + } + + + @Override + public MetaData getMetaData() { + throw new UnsupportedOperationException(); + + } + + private static class MockDimension implements Dimension { + @Override + public List getHierarchies() { + throw new UnsupportedOperationException(); + } + + @Override + public boolean isMeasures() { + throw new UnsupportedOperationException(); + } + + @Override + public DimensionType getDimensionType() { + throw new UnsupportedOperationException(); + } + + @Override + public Catalog getCatalog() { + throw new UnsupportedOperationException(); + } + + @Override + public String getUniqueName() { + throw new UnsupportedOperationException(); + } + + @Override + public String getName() { + throw new UnsupportedOperationException(); + } + + @Override + public String getDescription() { + throw new UnsupportedOperationException(); + } + + @Override + public boolean isVisible() { + throw new UnsupportedOperationException(); + } + + @Override + public OlapElement lookupChild( + CatalogReader schemaReader, + Segment s, MatchType matchType ) { + throw new UnsupportedOperationException(); + } + + @Override + public String getQualifiedName() { + throw new UnsupportedOperationException(); + } + + @Override + public String getCaption() { + throw new UnsupportedOperationException(); + } + + @Override + public String getLocalized( LocalizedProperty prop, Locale locale ) { + throw new UnsupportedOperationException(); + } + + @Override + public Hierarchy getHierarchy() { + throw new UnsupportedOperationException(); + } + + @Override + public Dimension getDimension() { + throw new UnsupportedOperationException(); + } + + @Override + public MetaData getMetaData() { + throw new UnsupportedOperationException(); + } + + @Override + public Cube getCube() { + return null; + } + + } + +} diff --git a/common/src/test/java/org/eclipse/daanse/olap/function/def/union/UnionFunDefTest.java b/common/src/test/java/org/eclipse/daanse/olap/function/def/union/UnionFunDefTest.java new file mode 100644 index 00000000..881f02d4 --- /dev/null +++ b/common/src/test/java/org/eclipse/daanse/olap/function/def/union/UnionFunDefTest.java @@ -0,0 +1,220 @@ +/* + * This software is subject to the terms of the Eclipse Public License v1.0 + * Agreement, available at the following URL: + * http://www.eclipse.org/legal/epl-v10.html. + * You must accept the terms of that agreement to use this software. + * + * Copyright (c) 2002-2017 Hitachi Vantara. All rights reserved. + * + * ---- All changes after Fork in 2023 ------------------------ + * + * Project: Eclipse daanse + * + * Copyright (c) 2023 Contributors to the Eclipse Foundation. + * + * 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/ + * + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors after Fork in 2023: + * SmartCity Jena - initial + */ + +package org.eclipse.daanse.olap.function.def.union; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyBoolean; +import static org.mockito.Mockito.doCallRealMethod; +import static org.mockito.Mockito.mock; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +import org.eclipse.daanse.olap.api.calc.Calc; +import org.eclipse.daanse.olap.api.calc.todo.TupleList; +import org.eclipse.daanse.olap.api.element.Member; +import org.eclipse.daanse.olap.api.element.MetaData; +import org.eclipse.daanse.olap.api.element.Property; +import org.eclipse.daanse.olap.api.function.FunctionDefinition; +import org.eclipse.daanse.olap.api.query.component.Expression; +import org.eclipse.daanse.olap.api.type.SetType; +import org.eclipse.daanse.olap.calc.base.type.tuplebase.ArrayTupleList; +import org.eclipse.daanse.olap.calc.base.type.tuplebase.UnaryTupleList; +import org.eclipse.daanse.olap.element.MemberBase; +import org.eclipse.daanse.olap.function.def.crossjoin.CrossJoinFunDef; +import org.eclipse.daanse.olap.function.def.crossjoin.CrossJoinTest; +import org.eclipse.daanse.olap.function.def.crossjoin.ImmutableListCalc; +import org.eclipse.daanse.olap.query.component.ResolvedFunCallImpl; +import org.junit.jupiter.api.Test; +import org.mockito.Mockito; +import org.slf4j.Logger; + +/** + * Tests for UnionFunDef + * + * @author Yury Bakhmutski + */ +class UnionFunDefTest { + + /** + * Test for MONDRIAN-2250 issue. + * Tests that the result is independent on the hashCode. + * For this purpose MemberForTest with rewritten hashCode is used. + * + * Tuples are gotten from customer attachments. + */ + @Test + void testMondrian2250() { + Member[] dates = new Member[4]; + for (int i = 25; i < 29; i++) { + dates[i - 25] = + new MemberForTest("[Consumption Date.Calendar].[2014-07-" + i + "]"); + } + List list = Arrays.asList(dates); + UnaryTupleList unaryTupleList = new UnaryTupleList(list); + + Member consumptionMethod = + new MemberForTest("[Consumption Method].[PVR]"); + Member measuresAverageTimeshift = + new MemberForTest("[Measures].[Average Timeshift]"); + String[] hours = { "00", "14", "15", "16", "23" }; + Member[] times = new Member[5]; + for (int i = 0; i < hours.length; i++) { + times[i] = + new MemberForTest("[Consumption Time.Time].[" + hours[i] + ":00]"); + } + + int arity = 3; + ArrayTupleList arrayTupleList = new ArrayTupleList(arity); + for (Member time : times) { + List currentList = new ArrayList(3); + currentList.add(consumptionMethod); + currentList.add(measuresAverageTimeshift); + currentList.add(time); + arrayTupleList.add(currentList); + } + + CrossJoinFunDef crossJoinFunDef = + new CrossJoinFunDef(new CrossJoinTest.NullFunDef().getFunctionMetaData()); + Expression[] expMock = new Expression[1]; + expMock[0] = mock(Expression.class); + ResolvedFunCallImpl resolvedFunCall = + new ResolvedFunCallImpl(mock(FunctionDefinition.class), expMock, mock(SetType.class)); + Calc[] calcs = new Calc[1]; + calcs[0] = Mockito.mock(Calc.class); + ImmutableListCalc immutableListCalc = + new ImmutableListCalc( + resolvedFunCall, calcs, crossJoinFunDef.getCtag()); + + TupleList listForUnion1 = + immutableListCalc.makeList(unaryTupleList, arrayTupleList); + + List list2 = Arrays.asList(dates); + UnaryTupleList unaryTupleList2 = new UnaryTupleList(list2); + + Member measuresTotalViewingTime = + new MemberForTest("[Measures].[Total Viewing Time]"); + ArrayTupleList arrayTupleList2 = new ArrayTupleList(arity); + for (Member time : times) { + List currentList = new ArrayList(3); + currentList.add(consumptionMethod); + currentList.add(measuresTotalViewingTime); + currentList.add(time); + arrayTupleList2.add(currentList); + } + + TupleList listForUnion2 = + immutableListCalc.makeList(unaryTupleList2, arrayTupleList2); + + UnionCalc unionFunDefMock = mock(UnionCalc.class); + doCallRealMethod().when(unionFunDefMock).union( + any(), any(), anyBoolean()); + + TupleList tupleList = + unionFunDefMock.union(listForUnion1, listForUnion2, false); + System.out.println(tupleList); + assertEquals(40, tupleList.size()); + } + + + private class MemberForTest extends MemberBase { + private String identifer; + + public MemberForTest(String identifer) { + this.identifer = identifer; + } + + @Override + public String getUniqueName() { + return identifer; + } + + @Override + public int hashCode() { + return 31; + } + + @Override + public void setName(String name) { + } + + @Override + public boolean isCalculatedInQuery() { + return false; + } + + @Override + public Object getPropertyValue(String propertyName) { + return null; + } + + @Override + public Object getPropertyValue(String propertyName, boolean matchCase) { + return null; + } + + @Override + public void setProperty(String name, Object value) { + + } + + @Override + public Property[] getProperties() { + return null; + } + + @Override + public int getDepth() { + return 0; + } + + @Override + public int compareTo(Object arg0) { + return 0; + } + + @Override + public MetaData getMetaData() { + return null; + } + + @Override + public String getName() { + return null; + } + + @Override + public Object getCaptionValue() { + return null; + } + + @Override + protected Logger getLogger() { + return null; + } + } +} diff --git a/common/src/test/java/org/eclipse/daanse/olap/util/I18nTest.java b/common/src/test/java/org/eclipse/daanse/olap/util/I18nTest.java new file mode 100644 index 00000000..2379d4ee --- /dev/null +++ b/common/src/test/java/org/eclipse/daanse/olap/util/I18nTest.java @@ -0,0 +1,81 @@ +/* + * This software is subject to the terms of the Eclipse Public License v1.0 + * Agreement, available at the following URL: + * http://www.eclipse.org/legal/epl-v10.html. + * You must accept the terms of that agreement to use this software. + * + * Copyright (c) 2002-2017 Hitachi Vantara.. All rights reserved. + * + * ---- All changes after Fork in 2023 ------------------------ + * + * Project: Eclipse daanse + * + * Copyright (c) 2023 Contributors to the Eclipse Foundation. + * + * 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/ + * + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors after Fork in 2023: + * SmartCity Jena - initial + */ +package org.eclipse.daanse.olap.util; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +import java.util.Calendar; +import java.util.Locale; + +import org.junit.jupiter.api.Test; + +/** + * Test suite for internalization and localization. + * + * @see mondrian.util.FormatTest + * + * @author jhyde + * @since September 22, 2005 + */ +class I18nTest { + public static final char Euro = '\u20AC'; + public static final char Nbsp = ' '; + public static final char EA = '\u00e9'; // e acute + public static final char UC = '\u00FB'; // u circumflex + + @Test + void testFormat() { + // Make sure Util is loaded, so that the LocaleFormatFactory gets + // registered. +// discard(Util.NL); + + Locale spanish = new Locale("es", "ES"); + Locale german = new Locale("de", "DE"); + + // Thousands and decimal separators are different in Spain + Format numFormat = new Format("#,000.00", spanish); + assertEquals(numFormat.format(new Double(123456.789)), "123.456,79"); + + // Currency too + Format currencyFormat = new Format("Currency", spanish); + assertEquals( + "1.234.567,79 €", + currencyFormat.format(new Double(1234567.789))); + + // Dates + Format dateFormat = new Format("Medium Date", spanish); + Calendar calendar = Calendar.getInstance(); + calendar.set(Calendar.YEAR, 2005); + calendar.set(Calendar.MONTH, 0); // January, 0-based + calendar.set(Calendar.DATE, 22); + java.util.Date date = calendar.getTime(); + assertEquals("22-ene-05", dateFormat.format(date)); + + // Dates in German + dateFormat = new Format("Long Date", german); + assertEquals("Samstag, Januar 22, 2005", dateFormat.format(date)); + } + + +} \ No newline at end of file