diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-27 16:51:28 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-27 16:51:28 +0000 |
commit | 940b4d1848e8c70ab7642901a68594e8016caffc (patch) | |
tree | eb72f344ee6c3d9b80a7ecc079ea79e9fba8676d /comphelper/qa | |
parent | Initial commit. (diff) | |
download | libreoffice-940b4d1848e8c70ab7642901a68594e8016caffc.tar.xz libreoffice-940b4d1848e8c70ab7642901a68594e8016caffc.zip |
Adding upstream version 1:7.0.4.upstream/1%7.0.4upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'comphelper/qa')
-rw-r--r-- | comphelper/qa/complex/comphelper/Map.java | 515 | ||||
-rw-r--r-- | comphelper/qa/complex/comphelper/SequenceOutputStreamUnitTest.java | 132 | ||||
-rw-r--r-- | comphelper/qa/complex/comphelper_all.sce | 19 | ||||
-rw-r--r-- | comphelper/qa/container/comphelper_ifcontainer.cxx | 144 | ||||
-rw-r--r-- | comphelper/qa/container/testifcontainer.cxx | 161 | ||||
-rw-r--r-- | comphelper/qa/string/test_string.cxx | 415 | ||||
-rw-r--r-- | comphelper/qa/unit/base64_test.cxx | 111 | ||||
-rw-r--r-- | comphelper/qa/unit/parallelsorttest.cxx | 101 | ||||
-rw-r--r-- | comphelper/qa/unit/syntaxhighlighttest.cxx | 122 | ||||
-rw-r--r-- | comphelper/qa/unit/test_guards.cxx | 57 | ||||
-rw-r--r-- | comphelper/qa/unit/test_hash.cxx | 134 | ||||
-rw-r--r-- | comphelper/qa/unit/threadpooltest.cxx | 55 | ||||
-rw-r--r-- | comphelper/qa/unit/types_test.cxx | 97 | ||||
-rw-r--r-- | comphelper/qa/unit/variadictemplates.cxx | 181 | ||||
-rw-r--r-- | comphelper/qa/weakbag/makefile.mk | 44 | ||||
-rw-r--r-- | comphelper/qa/weakbag/test_weakbag.cxx | 60 | ||||
-rw-r--r-- | comphelper/qa/weakbag/test_weakbag_noadditional.cxx | 25 |
17 files changed, 2373 insertions, 0 deletions
diff --git a/comphelper/qa/complex/comphelper/Map.java b/comphelper/qa/complex/comphelper/Map.java new file mode 100644 index 000000000..d01d1bef3 --- /dev/null +++ b/comphelper/qa/complex/comphelper/Map.java @@ -0,0 +1,515 @@ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * 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 . + */ + +package complex.comphelper; + +import com.sun.star.beans.Pair; +import com.sun.star.container.ContainerEvent; +import com.sun.star.container.XContainer; +import com.sun.star.container.XContainerListener; +import com.sun.star.container.XElementAccess; +import com.sun.star.container.XEnumerableMap; +import com.sun.star.container.XEnumeration; +import com.sun.star.container.XIdentifierAccess; +import com.sun.star.container.XMap; +import com.sun.star.container.XSet; +import com.sun.star.form.XFormComponent; +import com.sun.star.lang.EventObject; +import com.sun.star.lang.Locale; +import com.sun.star.lang.XMultiServiceFactory; +import com.sun.star.uno.Any; +import com.sun.star.uno.AnyConverter; +import com.sun.star.uno.Type; +import com.sun.star.uno.TypeClass; +import com.sun.star.uno.UnoRuntime; +import com.sun.star.uno.XInterface; +import java.util.HashSet; +import java.util.Set; + +import org.junit.AfterClass; +import org.junit.BeforeClass; +import org.junit.Test; +import org.openoffice.test.OfficeConnection; +import static org.junit.Assert.*; + +/** complex test case for the css.container.Map implementation + */ +public class Map +{ + private static String impl_getNth( int n ) + { + switch ( n % 10 ) + { + case 1: return n + "st"; + case 2: return n + "nd"; + default: return n + "th"; + } + } + + private static void impl_putAll( XMap _map, Object[] _keys, Object[] _values ) throws com.sun.star.uno.Exception + { + for ( int i=0; i<_keys.length; ++i ) + { + _map.put( _keys[i], _values[i] ); + } + } + + private static void impl_checkContent( XMap _map, Object[] _keys, Object[] _values, String _context ) throws com.sun.star.uno.Exception + { + for ( int i=0; i<_keys.length; ++i ) + { + assertTrue( _context + ": " + impl_getNth(i) + " key (" + _keys[i].toString() + ") not found in map", + _map.containsKey( _keys[i] ) ); + assertTrue( _context + ": " + impl_getNth(i) + " value (" + _values[i].toString() + ") not found in map", + _map.containsValue( _values[i] ) ); + assertEquals( _context + ": wrong value for " + impl_getNth(i) + " key (" + _keys[i] + ")", + _values[i], _map.get( _keys[i] ) ); + } + } + + @SuppressWarnings("unchecked") + private static void impl_checkMappings( Object[] _keys, Object[] _values, String _context ) throws com.sun.star.uno.Exception + { + System.out.println( "checking mapping " + _context + "..." ); + + Type keyType = AnyConverter.getType( _keys[0] ); + Type valueType = AnyConverter.getType( _values[0] ); + + // create a map for the given types + XMap map = com.sun.star.container.EnumerableMap.create( connection.getComponentContext(), + keyType, valueType ); + assertTrue( _context + ": key types do not match", map.getKeyType().equals( keyType ) ); + assertTrue( _context + ": value types do not match", map.getValueType().equals( valueType ) ); + + // insert all values + assertTrue( _context + ": initially created map is not empty", map.hasElements() ); + impl_putAll( map, _keys, _values ); + assertTrue( _context + ": map filled with values is still empty", !map.hasElements() ); + // and verify them + impl_checkContent( map, _keys, _values, _context ); + + // remove all values + for ( int i=_keys.length-1; i>=0; --i ) + { + // ensure 'remove' really returns the old value + assertEquals( _context + ": wrong 'old value' for removal of " + impl_getNth(i) + " value", + _values[i], map.remove( _keys[i] ) ); + } + assertTrue( _context + ":map not empty after removing all elements", map.hasElements() ); + + // insert again, and check whether 'clear' does what it should do + impl_putAll( map, _keys, _values ); + map.clear(); + assertTrue( _context + ": 'clear' does not empty the map", map.hasElements() ); + + // try the constructor which creates an immutable version + Pair< ?, ? >[] initialMappings = new Pair< ?, ? >[ _keys.length ]; + for ( int i=0; i<_keys.length; ++i ) + { + initialMappings[i] = new Pair< Object, Object >( _keys[i], _values[i] ); + } + map = com.sun.star.container.EnumerableMap.createImmutable( + connection.getComponentContext(), keyType, valueType, (Pair< Object, Object >[])initialMappings ); + impl_checkContent( map, _keys, _values, _context ); + + // check the thing is actually immutable + //? assureException( map, "clear", new Object[] {}, NoSupportException.class ); + //? assureException( map, "remove", new Class[] { Object.class }, new Object[] { _keys[0] }, NoSupportException.class ); + //? assureException( map, "put", new Class[] { Object.class, Object.class }, new Object[] { _keys[0], _values[0] }, NoSupportException.class ); + } + + @Test public void testSimpleKeyTypes() throws com.sun.star.uno.Exception + { + impl_checkMappings( + new Long[] { (long)1, (long)2, (long)3, (long)4, (long)5 }, + new Integer[] { 6, 7, 8, 9, 10 }, + "long->int" + ); + impl_checkMappings( + new Boolean[] { true, false }, + new Short[] { (short)1, (short)0 }, + "bool->short" + ); + impl_checkMappings( + new String[] { "one", "two", "three", "four", "five"}, + new String[] { "1", "2", "3", "4", "5" }, + "string->string" + ); + impl_checkMappings( + new Double[] { 1.2, 3.4, 5.6, 7.8, 9.10 }, + new Float[] { (float)1, (float)2, (float)3, (float)4, (float)5 }, + "double->float" + ); + impl_checkMappings( + new Float[] { (float)1, (float)2, (float)3, (float)4, (float)5 }, + new Double[] { 1.2, 3.4, 5.6, 7.8, 9.10 }, + "float->double" + ); + impl_checkMappings( + new Integer[] { 2, 9, 2005, 20, 11, 1970, 26, 3, 1974 }, + new String[] { "2nd", "September", "2005", "20th", "November", "1970", "26th", "March", "1974" }, + "int->string" + ); + } + + @Test public void testComplexKeyTypes() throws com.sun.star.uno.Exception + { + Type intType = new Type( Integer.class ); + Type longType = new Type( Long.class ); + Type msfType = new Type ( XMultiServiceFactory.class ); + + // css.uno.Type should be a valid key type + impl_checkMappings( + new Type[] { intType, longType, msfType }, + new String[] { intType.getTypeName(), longType.getTypeName(), msfType.getTypeName() }, + "type->string" + ); + + + // any UNO interface type should be a valid key type. + // Try with some form components (just because I like form components :), and the very first application + // for the newly implemented map will be to map XFormComponents to drawing shapes + String[] serviceNames = new String[] { "CheckBox", "ComboBox", "CommandButton", "DateField", "FileControl" }; + Object[] components = new Object[ serviceNames.length ]; + for ( int i=0; i<serviceNames.length; ++i ) + { + components[i] = getMSF().createInstance( "com.sun.star.form.component." + serviceNames[i] ); + } + // "normalize" the first component, so it has the property type + Type formComponentType = new Type( XFormComponent.class ); + components[0] = UnoRuntime.queryInterface( formComponentType.getZClass(), components[0] ); + impl_checkMappings( components, serviceNames, "XFormComponent->string" ); + + + // any UNO enum type should be a valid key type + impl_checkMappings( + new TypeClass[] { intType.getTypeClass(), longType.getTypeClass(), msfType.getTypeClass() }, + new Object[] { "foo", "bar", "42" }, + "enum->string" + ); + } + + private static Class<?> impl_getValueClassByPos( int _pos ) + { + Class<?> valueClass = null; + switch ( _pos ) + { + case 0: valueClass = Boolean.class; break; + case 1: valueClass = Short.class; break; + case 2: valueClass = Integer.class; break; + case 3: valueClass = Long.class; break; + case 4: valueClass = XInterface.class; break; + case 5: valueClass = XSet.class; break; + case 6: valueClass = XContainer.class; break; + case 7: valueClass = XIdentifierAccess.class; break; + case 8: valueClass = XElementAccess.class; break; + case 9: valueClass = com.sun.star.uno.Exception.class; break; + case 10: valueClass = com.sun.star.uno.RuntimeException.class; break; + case 11: valueClass = EventObject.class; break; + case 12: valueClass = ContainerEvent.class; break; + case 13: valueClass = Object.class; break; + default: + fail( "internal error: wrong position for getValueClass" ); + } + return valueClass; + } + + private Object impl_getSomeValueByTypePos( int _pos ) + { + Object someValue = null; + switch ( _pos ) + { + case 0: someValue = Boolean.FALSE; break; + case 1: someValue = Short.valueOf( (short)0 ); break; + case 2: someValue = Integer.valueOf( 0 ); break; + case 3: someValue = Long.valueOf( 0 ); break; + case 4: someValue = UnoRuntime.queryInterface( XInterface.class, new DummyInterface() ); break; + case 5: someValue = UnoRuntime.queryInterface( XSet.class, new DummySet() ); break; + case 6: someValue = UnoRuntime.queryInterface( XContainer.class, new DummyContainer() ); break; + case 7: someValue = UnoRuntime.queryInterface( XIdentifierAccess.class, new DummyIdentifierAccess() ); break; + case 8: someValue = UnoRuntime.queryInterface( XElementAccess.class, new DummyElementAccess() ); break; + case 9: someValue = new com.sun.star.uno.Exception(); break; + case 10: someValue = new com.sun.star.uno.RuntimeException(); break; + case 11: someValue = new EventObject(); break; + case 12: someValue = new ContainerEvent(); break; + case 13: someValue = new Locale(); break; // just use *any* value which does not conflict with the others + default: + fail( "internal error: wrong position for getSomeValue" ); + } + return someValue; + } + + private static class DummyInterface implements XInterface + { + } + + private static class DummySet implements XSet + { + public boolean has( Object arg0 ) { throw new UnsupportedOperationException( "Not implemented." ); } + public void insert( Object arg0 ) { throw new UnsupportedOperationException( "Not implemented." ); } + public void remove( Object arg0 ) { throw new UnsupportedOperationException( "Not implemented." ); } + public XEnumeration createEnumeration() { throw new UnsupportedOperationException( "Not implemented." ); } + public Type getElementType() { throw new UnsupportedOperationException( "Not implemented." ); } + public boolean hasElements() { throw new UnsupportedOperationException( "Not implemented." ); } + } + + private class DummyContainer implements XContainer + { + public void addContainerListener( XContainerListener arg0 ) { throw new UnsupportedOperationException( "Not implemented." ); } + public void removeContainerListener( XContainerListener arg0 ) { throw new UnsupportedOperationException( "Not implemented." ); } + } + + private class DummyIdentifierAccess implements XIdentifierAccess + { + public Object getByIdentifier( int arg0 ) { throw new UnsupportedOperationException( "Not implemented." ); } + public int[] getIdentifiers() { throw new UnsupportedOperationException( "Not implemented." ); } + public Type getElementType() { throw new UnsupportedOperationException( "Not implemented." ); } + public boolean hasElements() { throw new UnsupportedOperationException( "Not implemented." ); } + } + + private class DummyElementAccess implements XElementAccess + { + public Type getElementType() { throw new UnsupportedOperationException( "Not implemented." ); } + public boolean hasElements() { throw new UnsupportedOperationException( "Not implemented." ); } + } + + @Test public void testValueTypes() throws com.sun.star.uno.Exception + { + // type compatibility matrix: rows are the value types used to create the map, + // columns are the value types fed into the map. A value "1" means the respective type + // should be accepted. + Integer[][] typeCompatibility = new Integer[][] { + /* boolean */ new Integer[] { 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + /* short */ new Integer[] { 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + /* int */ new Integer[] { 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + /* long */ new Integer[] { 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + /* XInterface */ new Integer[] { 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0 }, + /* XSet */ new Integer[] { 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0 }, + /* XContainer */ new Integer[] { 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0 }, + /* XIdentifierAccess */ new Integer[] { 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0 }, + /* XElementAccess */ new Integer[] { 0, 0, 0, 0, 0, 1, 0, 1, 1, 0, 0, 0, 0, 0 }, + /* Exception */ new Integer[] { 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0 }, + /* RuntimeException */ new Integer[] { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0 }, + /* EventObject */ new Integer[] { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0 }, + /* ContainerEvent */ new Integer[] { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0 }, + /* any */ new Integer[] { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 }, + }; + // several asects are checked with this compatibility matrix: + // - if a map's value type is a scalar type, or a string, then nothing but this + // type should be accepted + // - if a map's value type is an interface type, then values should be accepted if + // they contain a derived interface, or the interface itself, or if they can be + // queried for this interface (actually, the latter rule is not tested with the + // above matrix) + // - if a map's value type is a struct or exception, then values should be accepted + // if they are of the given type, or of a derived type. + // - if a map's value type is "any", then, well, any value should be accepted + + for ( int valueTypePos = 0; valueTypePos != typeCompatibility.length; ++valueTypePos ) + { + com.sun.star.container.EnumerableMap.create( connection.getComponentContext(), + new Type( Integer.class ), new Type( impl_getValueClassByPos( valueTypePos ) ) ); + + for ( int checkTypePos = 0; checkTypePos != typeCompatibility[valueTypePos].length; ++checkTypePos ) + { + impl_getSomeValueByTypePos( checkTypePos ); + if ( typeCompatibility[valueTypePos][checkTypePos] != 0 ) + { + // expected to succeed +//? assureException( +//? "(" + valueTypePos + "," + checkTypePos + ") putting an " + +//? AnyConverter.getType( value ).getTypeName() + ", where " + +//? map.getValueType().getTypeName() + " is expected, should succeed", +//? map, "put", new Class[] { Object.class, Object.class }, new Object[] { key, value }, +//? null ); + } + else + { + // expected to fail +//? assureException( +//? "(" + valueTypePos + "," + checkTypePos + ") putting an " + +//? AnyConverter.getType( value ).getTypeName() + ", where " + +//? map.getValueType().getTypeName() + " is expected, should not succeed", +//? map, "put", new Class[] { Object.class, Object.class }, new Object[] { key, value }, +//? IllegalTypeException.class ); + } + } + } + } + + private interface CompareEqual + { + boolean areEqual( Object _lhs, Object _rhs ); + } + + private class DefaultCompareEqual implements CompareEqual + { + public boolean areEqual( Object _lhs, Object _rhs ) + { + return _lhs.equals( _rhs ); + } + } + + private class PairCompareEqual implements CompareEqual + { + public boolean areEqual( Object _lhs, Object _rhs ) + { + Pair< ?, ? > lhs = (Pair< ?, ? >)_lhs; + Pair< ?, ? > rhs = (Pair< ?, ? >)_rhs; + return lhs.First.equals( rhs.First ) && lhs.Second.equals( rhs.Second ); + } + } + + private void impl_verifyEnumerationContent( XEnumeration _enum, final Object[] _expectedElements, final String _context ) + throws com.sun.star.uno.Exception + { + // since we cannot assume the map to preserve the ordering in which the elements where inserted, + // we can only verify that all elements exist as expected, plus *no more* elements than expected + // are provided by the enumeration + Set<Integer> set = new HashSet<Integer>(); + for ( int i=0; i<_expectedElements.length; ++i ) + { + set.add( i ); + } + + CompareEqual comparator = _expectedElements[0].getClass().equals( Pair.class ) + ? new PairCompareEqual() + : new DefaultCompareEqual(); + + for ( int i=0; i<_expectedElements.length; ++i ) + { + assertTrue( _context + ": too few elements in the enumeration (still " + ( _expectedElements.length - i ) + " to go)", + _enum.hasMoreElements() ); + + Object nextElement = _enum.nextElement(); + if ( nextElement.getClass().equals( Any.class ) ) + { + nextElement = ((Any)nextElement).getObject(); + } + + int foundPos = -1; + for ( int j=0; j<_expectedElements.length; ++j ) + { + if ( comparator.areEqual( _expectedElements[j], nextElement ) ) + { + foundPos = j; + break; + } + } + + assertTrue( _context + ": '" + nextElement.toString() + "' is not expected in the enumeration", + set.contains( foundPos ) ); + set.remove( foundPos ); + } + assertTrue( _context + ": too many elements returned by the enumeration", set.isEmpty() ); + } + + @Test public void testEnumerations() throws com.sun.star.uno.Exception + { + // fill a map + final String[] keys = new String[] { "This", "is", "an", "enumeration", "test" }; + final String[] values = new String[] { "for", "the", "map", "implementation", "." }; + XEnumerableMap map = com.sun.star.container.EnumerableMap.create( connection.getComponentContext(), new Type( String.class ), new Type( String.class ) ); + impl_putAll( map, keys, values ); + + final Pair< ?, ? >[] paired = new Pair< ?, ? >[ keys.length ]; + for ( int i=0; i<keys.length; ++i ) + { + paired[i] = new Pair< Object, Object >( keys[i], values[i] ); + } + + // create non-isolated enumerators, and check their content + XEnumeration enumerateKeys = map.createKeyEnumeration( false ); + XEnumeration enumerateValues = map.createValueEnumeration( false ); + XEnumeration enumerateAll = map.createElementEnumeration( false ); + impl_verifyEnumerationContent( enumerateKeys, keys, "key enumeration" ); + impl_verifyEnumerationContent( enumerateValues, values, "value enumeration" ); + impl_verifyEnumerationContent( enumerateAll, paired, "content enumeration" ); + + // all enumerators above have been created as non-isolated iterators, so they're expected to die when + // the underlying map changes + map.remove( keys[0] ); +//? assureException( enumerateKeys, "hasMoreElements", new Object[] {}, DisposedException.class ); +//? assureException( enumerateValues, "hasMoreElements", new Object[] {}, DisposedException.class ); +//? assureException( enumerateAll, "hasMoreElements", new Object[] {}, DisposedException.class ); + + // now try with isolated iterators + map.put( keys[0], values[0] ); + enumerateKeys = map.createKeyEnumeration( true ); + enumerateValues = map.createValueEnumeration( true ); + enumerateAll = map.createElementEnumeration( true ); + map.put( "additional", "value" ); + impl_verifyEnumerationContent( enumerateKeys, keys, "key enumeration" ); + impl_verifyEnumerationContent( enumerateValues, values, "value enumeration" ); + impl_verifyEnumerationContent( enumerateAll, paired, "content enumeration" ); + } + + @Test public void testSpecialValues() throws com.sun.star.uno.Exception + { + final Double[] keys = new Double[] { new Double( 0 ), Double.POSITIVE_INFINITY, Double.NEGATIVE_INFINITY }; + final Double[] values = new Double[] { Double.NEGATIVE_INFINITY, Double.POSITIVE_INFINITY, new Double( 0 ) }; + + XEnumerableMap map = com.sun.star.container.EnumerableMap.create( connection.getComponentContext(), new Type( Double.class ), new Type( Double.class ) ); + impl_putAll( map, keys, values ); + + assertTrue( "containsKey( Double.+INF failed", map.containsKey( Double.POSITIVE_INFINITY ) ); + assertTrue( "containsKey( Double.-INF failed", map.containsKey( Double.NEGATIVE_INFINITY ) ); + assertTrue( "containsKey( 0 ) failed", map.containsKey( new Double( 0 ) ) ); + + assertTrue( "containsValue( Double.+INF ) failed", map.containsValue( Double.POSITIVE_INFINITY ) ); + assertTrue( "containsValue( Double.-INF ) failed", map.containsValue( Double.NEGATIVE_INFINITY ) ); + assertTrue( "containsValue( 0 ) failed", map.containsValue( new Double( 0 ) ) ); + + // put and containsKey should reject Double.NaN as key +//? assureException( "Double.NaN should not be allowed as key in a call to 'put'", map, "put", +//? new Class[] { Object.class, Object.class }, new Object[] { Double.NaN, new Double( 0 ) }, +//? com.sun.star.lang.IllegalArgumentException.class ); +//? assureException( "Double.NaN should not be allowed as key in a call to 'containsKey'", map, "containsKey", +//? new Class[] { Object.class }, new Object[] { Double.NaN }, +//? com.sun.star.lang.IllegalArgumentException.class ); + + // ditto for put and containsValue +//? assureException( "Double.NaN should not be allowed as value in a call to 'put'", map, "put", +//? new Class[] { Object.class, Object.class }, new Object[] { new Double( 0 ), Double.NaN }, +//? com.sun.star.lang.IllegalArgumentException.class ); +//? assureException( "Double.NaN should not be allowed as key in a call to 'containsValue'", map, "containsValue", +//? new Class[] { Object.class }, new Object[] { Double.NaN }, +//? com.sun.star.lang.IllegalArgumentException.class ); + } + + + private static XMultiServiceFactory getMSF() + { + return UnoRuntime.queryInterface(XMultiServiceFactory.class, connection.getComponentContext().getServiceManager()); + } + + // setup and close connections + @BeforeClass public static void setUpConnection() throws Exception { + System.out.println("setUpConnection()"); + connection.setUp(); + } + + @AfterClass public static void tearDownConnection() + throws InterruptedException, com.sun.star.uno.Exception + { + System.out.println("tearDownConnection()"); + connection.tearDown(); + } + + private static final OfficeConnection connection = new OfficeConnection(); +} diff --git a/comphelper/qa/complex/comphelper/SequenceOutputStreamUnitTest.java b/comphelper/qa/complex/comphelper/SequenceOutputStreamUnitTest.java new file mode 100644 index 000000000..03906134b --- /dev/null +++ b/comphelper/qa/complex/comphelper/SequenceOutputStreamUnitTest.java @@ -0,0 +1,132 @@ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * 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 . + */ +package complex.comphelper; + +import com.sun.star.lang.XMultiServiceFactory; +import com.sun.star.uno.UnoRuntime; + +import com.sun.star.io.XSequenceOutputStream; +import com.sun.star.io.XSeekableInputStream; + +import java.util.Random; +import org.junit.After; +import org.junit.AfterClass; +import org.junit.Before; +import org.junit.BeforeClass; +import org.junit.Test; +import org.openoffice.test.OfficeConnection; +import static org.junit.Assert.*; + +/* Document. + */ + +public class SequenceOutputStreamUnitTest +{ + private XMultiServiceFactory m_xMSF = null; + + @Before public void before() { + try { + m_xMSF = getMSF(); + } catch (Exception e) { + fail ("Cannot create service factory!"); + } + if (m_xMSF==null) { + fail ("Cannot create service factory!"); + } + } + + @After public void after() { + m_xMSF = null; + } + + @Test public void test () { + try { + final int nBytesCnt = 20; + + //create SequenceOutputStream + Object oSequenceOutputStream = m_xMSF.createInstance ( + "com.sun.star.io.SequenceOutputStream" ); + XSequenceOutputStream xSeqOutStream = + UnoRuntime.queryInterface ( + XSequenceOutputStream.class, oSequenceOutputStream ); + + //write something to the stream + byte pBytesOriginal[] = new byte [nBytesCnt]; + Random oRandom = new Random(); + oRandom.nextBytes (pBytesOriginal); + xSeqOutStream.writeBytes (pBytesOriginal); + + // Append the same content once again + xSeqOutStream.writeBytes (pBytesOriginal); + + byte pBytesWritten[] = xSeqOutStream.getWrittenBytes (); + assertTrue( "SequenceOutputStream::getWrittenBytes() - wrong amount of bytes returned", + pBytesWritten.length == nBytesCnt * 2 ); + + //create SequenceInputstream + Object pArgs[] = new Object[1]; + pArgs[0] = pBytesWritten; + Object oSequenceInputStream = m_xMSF.createInstanceWithArguments ( + "com.sun.star.io.SequenceInputStream", pArgs ); + XSeekableInputStream xSeekableInStream = + UnoRuntime.queryInterface ( + XSeekableInputStream.class, oSequenceInputStream ); + + //read from the stream + byte pBytesRead[][] = new byte [1][nBytesCnt*2]; + int nBytesCountRead = xSeekableInStream.readBytes ( pBytesRead, pBytesRead[0].length + 1 ); + + assertTrue( "SequenceInputStream::readBytes() - wrong amount of bytes returned " + pBytesRead[0].length + " vs " + (nBytesCountRead), + pBytesRead[0].length == nBytesCountRead); + + //close the streams + xSeqOutStream.closeOutput (); + xSeekableInStream.closeInput (); + + //compare the original, written and read arrays + for ( int i = 0; i < nBytesCnt * 2; ++i ) { + assertTrue( "Written array not identical to original array. Position: " + i, + pBytesOriginal[i % nBytesCnt] == pBytesWritten[i] ); + assertTrue( "Read array not identical to original array. Position: " + i, + pBytesOriginal[i % nBytesCnt] == pBytesRead[0][i] ); + } + } catch ( Exception e ) { + fail ( "Exception: " + e ); + } + } + + private static XMultiServiceFactory getMSF() + { + return UnoRuntime.queryInterface(XMultiServiceFactory.class, connection.getComponentContext().getServiceManager()); + } + + // setup and close connections + @BeforeClass public static void setUpConnection() throws Exception { + System.out.println("setUpConnection()"); + connection.setUp(); + } + + @AfterClass public static void tearDownConnection() + throws InterruptedException, com.sun.star.uno.Exception + { + System.out.println("tearDownConnection()"); + connection.tearDown(); + } + + private static final OfficeConnection connection = new OfficeConnection(); +} diff --git a/comphelper/qa/complex/comphelper_all.sce b/comphelper/qa/complex/comphelper_all.sce new file mode 100644 index 000000000..5ee5f941f --- /dev/null +++ b/comphelper/qa/complex/comphelper_all.sce @@ -0,0 +1,19 @@ +# +# This file is part of the LibreOffice project. +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# This file incorporates work covered by the following license notice: +# +# 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 . +# +-o complex.comphelper.SequenceOutputStreamUnitTest +-o complex.comphelper.Map diff --git a/comphelper/qa/container/comphelper_ifcontainer.cxx b/comphelper/qa/container/comphelper_ifcontainer.cxx new file mode 100644 index 000000000..4d28c496f --- /dev/null +++ b/comphelper/qa/container/comphelper_ifcontainer.cxx @@ -0,0 +1,144 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * 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 . + */ + +#include <sal/types.h> + +#include <cppunit/TestFixture.h> +#include <cppunit/extensions/HelperMacros.h> +#include <cppunit/plugin/TestPlugIn.h> + +#include <com/sun/star/lang/XEventListener.hpp> +#include <comphelper/interfacecontainer2.hxx> +#include <cppuhelper/implbase.hxx> + +using namespace com::sun::star; +using namespace com::sun::star::uno; +using namespace com::sun::star::lang; + +namespace { + +struct ContainerStats { + int m_nAlive; + int m_nDisposed; + ContainerStats() : m_nAlive(0), m_nDisposed(0) {} +}; + +class ContainerListener : public cppu::WeakImplHelper< XEventListener > +{ + ContainerStats * const m_pStats; +public: + explicit ContainerListener(ContainerStats *pStats) + : m_pStats(pStats) { m_pStats->m_nAlive++; } + virtual ~ContainerListener() override { m_pStats->m_nAlive--; } + virtual void SAL_CALL disposing( const EventObject& ) override + { + m_pStats->m_nDisposed++; + } +}; + +} + +namespace comphelper_ifcontainer +{ + static const int nTests = 10; + class IfTest : public CppUnit::TestFixture + { + osl::Mutex m_aGuard; + public: + void testCreateDispose() + { + ContainerStats aStats; + comphelper::OInterfaceContainerHelper2 *pContainer; + + pContainer = new comphelper::OInterfaceContainerHelper2(m_aGuard); + + CPPUNIT_ASSERT_EQUAL_MESSAGE("Empty container not empty", + static_cast<sal_Int32>(0), pContainer->getLength()); + + int i; + for (i = 0; i < nTests; i++) + { + Reference<XEventListener> xRef = new ContainerListener(&aStats); + int nNewLen = pContainer->addInterface(xRef); + + CPPUNIT_ASSERT_EQUAL_MESSAGE("addition length mismatch", + i + 1, nNewLen); + CPPUNIT_ASSERT_EQUAL_MESSAGE("addition length mismatch", + static_cast<sal_Int32>(i + 1), pContainer->getLength()); + } + CPPUNIT_ASSERT_EQUAL_MESSAGE("alive count mismatch", + nTests, aStats.m_nAlive); + + EventObject aObj; + pContainer->disposeAndClear(aObj); + + CPPUNIT_ASSERT_EQUAL_MESSAGE("dispose count mismatch", + nTests, aStats.m_nDisposed); + CPPUNIT_ASSERT_EQUAL_MESSAGE("leaked container left alive", + 0, aStats.m_nAlive); + + delete pContainer; + } + + void testEnumerate() + { + int i; + ContainerStats aStats; + comphelper::OInterfaceContainerHelper2 *pContainer; + pContainer = new comphelper::OInterfaceContainerHelper2(m_aGuard); + + std::vector< Reference< XEventListener > > aListeners; + for (i = 0; i < nTests; i++) + { + Reference<XEventListener> xRef = new ContainerListener(&aStats); + pContainer->addInterface(xRef); + aListeners.push_back(xRef); + } + std::vector< Reference< XInterface > > aElements = pContainer->getElements(); + + CPPUNIT_ASSERT_EQUAL_MESSAGE("query contents", + nTests, static_cast<int>(aElements.size())); + if (static_cast<int>(aElements.size()) == nTests) + { + for (i = 0; i < nTests; i++) + { + CPPUNIT_ASSERT_MESSAGE("mismatching elements", + bool(aElements[i] == aListeners[i])); + } + } + pContainer->clear(); + + CPPUNIT_ASSERT_EQUAL_MESSAGE("non-empty container post clear", + static_cast<sal_Int32>(0), pContainer->getLength()); + delete pContainer; + } + + // Automatic registration code + CPPUNIT_TEST_SUITE(IfTest); + CPPUNIT_TEST(testCreateDispose); + CPPUNIT_TEST(testEnumerate); + CPPUNIT_TEST_SUITE_END(); + }; +} // namespace cppu_ifcontainer + +CPPUNIT_TEST_SUITE_REGISTRATION(comphelper_ifcontainer::IfTest); + +CPPUNIT_PLUGIN_IMPLEMENT(); + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/comphelper/qa/container/testifcontainer.cxx b/comphelper/qa/container/testifcontainer.cxx new file mode 100644 index 000000000..d096b8fd8 --- /dev/null +++ b/comphelper/qa/container/testifcontainer.cxx @@ -0,0 +1,161 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * 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 . + */ + +#include <cppunit/TestAssert.h> +#include <cppunit/TestFixture.h> +#include <cppunit/extensions/HelperMacros.h> +#include <osl/mutex.hxx> +#include <comphelper/interfacecontainer2.hxx> +#include <cppuhelper/implbase.hxx> +#include <com/sun/star/beans/XVetoableChangeListener.hpp> + +using namespace ::osl; +using namespace ::com::sun::star::lang; +using namespace ::com::sun::star::beans; +using namespace ::com::sun::star::uno; + +namespace +{ + +class TestInterfaceContainer2: public CppUnit::TestFixture +{ +public: + void test1(); + + CPPUNIT_TEST_SUITE(TestInterfaceContainer2); + CPPUNIT_TEST(test1); + CPPUNIT_TEST_SUITE_END(); +}; + +class TestListener : public cppu::WeakImplHelper< XVetoableChangeListener > +{ +public: + // Methods + virtual void SAL_CALL disposing( const css::lang::EventObject& /*Source*/ ) override + { + + } + + virtual void SAL_CALL vetoableChange( const css::beans::PropertyChangeEvent& /*aEvent*/ ) override + { + + } +}; + +void TestInterfaceContainer2::test1() +{ + Mutex mutex; + + { + comphelper::OInterfaceContainerHelper2 helper( mutex ); + + Reference< XVetoableChangeListener > r1 = new TestListener; + Reference< XVetoableChangeListener > r2 = new TestListener; + Reference< XVetoableChangeListener > r3 = new TestListener; + + helper.addInterface( r1 ); + helper.addInterface( r2 ); + helper.addInterface( r3 ); + + helper.disposeAndClear( EventObject() ); + } + + { + comphelper::OInterfaceContainerHelper2 helper( mutex ); + + Reference< XVetoableChangeListener > r1 = new TestListener; + Reference< XVetoableChangeListener > r2 = new TestListener; + Reference< XVetoableChangeListener > r3 = new TestListener; + + helper.addInterface( r1 ); + helper.addInterface( r2 ); + helper.addInterface( r3 ); + + comphelper::OInterfaceIteratorHelper2 iterator( helper ); + + while( iterator.hasMoreElements() ) + static_cast<XVetoableChangeListener*>(iterator.next())->vetoableChange( PropertyChangeEvent() ); + + helper.disposeAndClear( EventObject() ); + } + + { + comphelper::OInterfaceContainerHelper2 helper( mutex ); + + Reference< XVetoableChangeListener > r1 = new TestListener; + Reference< XVetoableChangeListener > r2 = new TestListener; + Reference< XVetoableChangeListener > r3 = new TestListener; + + helper.addInterface( r1 ); + helper.addInterface( r2 ); + helper.addInterface( r3 ); + + comphelper::OInterfaceIteratorHelper2 iterator( helper ); + + static_cast<XVetoableChangeListener*>(iterator.next())->vetoableChange( PropertyChangeEvent() ); + iterator.remove(); + static_cast<XVetoableChangeListener*>(iterator.next())->vetoableChange( PropertyChangeEvent() ); + iterator.remove(); + static_cast<XVetoableChangeListener*>(iterator.next())->vetoableChange( PropertyChangeEvent() ); + iterator.remove(); + + CPPUNIT_ASSERT_EQUAL( static_cast<sal_Int32>(0), helper.getLength() ); + helper.disposeAndClear( EventObject() ); + } + + { + comphelper::OInterfaceContainerHelper2 helper( mutex ); + + Reference< XVetoableChangeListener > r1 = new TestListener; + Reference< XVetoableChangeListener > r2 = new TestListener; + Reference< XVetoableChangeListener > r3 = new TestListener; + + helper.addInterface( r1 ); + helper.addInterface( r2 ); + helper.addInterface( r3 ); + + { + comphelper::OInterfaceIteratorHelper2 iterator( helper ); + while( iterator.hasMoreElements() ) + { + Reference< XVetoableChangeListener > r = static_cast<XVetoableChangeListener*>(iterator.next()); + if( r == r1 ) + iterator.remove(); + } + } + CPPUNIT_ASSERT_EQUAL( static_cast<sal_Int32>(2), helper.getLength() ); + { + comphelper::OInterfaceIteratorHelper2 iterator( helper ); + while( iterator.hasMoreElements() ) + { + Reference< XVetoableChangeListener > r = static_cast<XVetoableChangeListener*>(iterator.next()); + CPPUNIT_ASSERT( r != r1 ); + CPPUNIT_ASSERT( r == r2 || r == r3 ); + } + } + + helper.disposeAndClear( EventObject() ); + } +} + +CPPUNIT_TEST_SUITE_REGISTRATION(TestInterfaceContainer2); + +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/comphelper/qa/string/test_string.cxx b/comphelper/qa/string/test_string.cxx new file mode 100644 index 000000000..14bc3f7ce --- /dev/null +++ b/comphelper/qa/string/test_string.cxx @@ -0,0 +1,415 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * 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 . + */ + +#include <comphelper/string.hxx> +#include <cppuhelper/implbase.hxx> +#include <com/sun/star/i18n/CharType.hpp> +#include <com/sun/star/i18n/XBreakIterator.hpp> +#include <com/sun/star/i18n/XCollator.hpp> + +#include <cppunit/TestAssert.h> +#include <cppunit/TestFixture.h> +#include <cppunit/extensions/HelperMacros.h> +#include <cppunit/plugin/TestPlugIn.h> +#include <rtl/string.hxx> +#include <rtl/ustring.hxx> + +namespace { + +class TestString: public CppUnit::TestFixture +{ +public: + void testNatural(); + void testStripStart(); + void testStripEnd(); + void testStrip(); + void testToken(); + void testTokenCount(); + void testDecimalStringToNumber(); + void testIsdigitAsciiString(); + void testReverseString(); + void testSplit(); + void testRemoveAny(); + + CPPUNIT_TEST_SUITE(TestString); + CPPUNIT_TEST(testNatural); + CPPUNIT_TEST(testStripStart); + CPPUNIT_TEST(testStripEnd); + CPPUNIT_TEST(testStrip); + CPPUNIT_TEST(testToken); + CPPUNIT_TEST(testTokenCount); + CPPUNIT_TEST(testDecimalStringToNumber); + CPPUNIT_TEST(testIsdigitAsciiString); + CPPUNIT_TEST(testReverseString); + CPPUNIT_TEST(testSplit); + CPPUNIT_TEST(testRemoveAny); + CPPUNIT_TEST_SUITE_END(); +}; + +void TestString::testDecimalStringToNumber() +{ + OUString s1("1234"); + CPPUNIT_ASSERT_EQUAL(sal_uInt32(1234), comphelper::string::decimalStringToNumber(s1)); + s1 += u"\u07C6"; + CPPUNIT_ASSERT_EQUAL(sal_uInt32(12346), comphelper::string::decimalStringToNumber(s1)); + // Codepoints on 2 16bits words + sal_uInt32 utf16String[] = { 0x1D7FE /* 8 */, 0x1D7F7 /* 1 */}; + s1 = OUString(utf16String, 2); + CPPUNIT_ASSERT_EQUAL(sal_uInt32(81), comphelper::string::decimalStringToNumber(s1)); +} + +void TestString::testIsdigitAsciiString() +{ + OString s1("1234"); + CPPUNIT_ASSERT_EQUAL(true, comphelper::string::isdigitAsciiString(s1)); + + OString s2("1A34"); + CPPUNIT_ASSERT_EQUAL(false, comphelper::string::isdigitAsciiString(s2)); + + OString s3; + CPPUNIT_ASSERT_EQUAL(true, comphelper::string::isdigitAsciiString(s3)); +} + +using namespace ::com::sun::star; + +class testCollator : public cppu::WeakImplHelper< i18n::XCollator > +{ +public: + virtual sal_Int32 SAL_CALL compareSubstring( + const OUString& str1, sal_Int32 off1, sal_Int32 len1, + const OUString& str2, sal_Int32 off2, sal_Int32 len2) override + { + return str1.copy(off1, len1).compareTo(str2.copy(off2, len2)); + } + virtual sal_Int32 SAL_CALL compareString( + const OUString& str1, + const OUString& str2) override + { + return str1.compareTo(str2); + } + virtual sal_Int32 SAL_CALL loadDefaultCollator(const lang::Locale&, sal_Int32) override {return 0;} + virtual sal_Int32 SAL_CALL loadCollatorAlgorithm(const OUString&, + const lang::Locale&, sal_Int32) override {return 0;} + virtual void SAL_CALL loadCollatorAlgorithmWithEndUserOption(const OUString&, + const lang::Locale&, const uno::Sequence< sal_Int32 >&) override {} + virtual uno::Sequence< OUString > SAL_CALL listCollatorAlgorithms(const lang::Locale&) override + { + return uno::Sequence< OUString >(); + } + virtual uno::Sequence< sal_Int32 > SAL_CALL listCollatorOptions(const OUString&) override + { + return uno::Sequence< sal_Int32 >(); + } +}; + +#define IS_DIGIT(CHAR) (((CHAR) >= 48) && ((CHAR <= 57))) + +class testBreakIterator : public cppu::WeakImplHelper< i18n::XBreakIterator > +{ +public: + virtual sal_Int32 SAL_CALL nextCharacters( const OUString&, sal_Int32, + const lang::Locale&, sal_Int16, sal_Int32, sal_Int32& ) override {return -1;} + virtual sal_Int32 SAL_CALL previousCharacters( const OUString&, sal_Int32, + const lang::Locale&, sal_Int16, sal_Int32, sal_Int32& ) override {return -1;} + + virtual i18n::Boundary SAL_CALL previousWord( const OUString&, sal_Int32, + const lang::Locale&, sal_Int16) override + { return i18n::Boundary(); } + virtual i18n::Boundary SAL_CALL nextWord( const OUString&, sal_Int32, + const lang::Locale&, sal_Int16) override + { return i18n::Boundary(); } + virtual i18n::Boundary SAL_CALL getWordBoundary( const OUString&, sal_Int32, + const lang::Locale&, sal_Int16, sal_Bool ) override + { return i18n::Boundary(); } + + virtual sal_Bool SAL_CALL isBeginWord( const OUString&, sal_Int32, + const lang::Locale&, sal_Int16 ) override + { return false; } + virtual sal_Bool SAL_CALL isEndWord( const OUString&, sal_Int32, + const lang::Locale& , sal_Int16 ) override + { return false; } + virtual sal_Int16 SAL_CALL getWordType( const OUString&, sal_Int32, + const lang::Locale& ) override + { return 0; } + + virtual sal_Int32 SAL_CALL beginOfSentence( const OUString&, sal_Int32, + const lang::Locale& ) override + { return 0; } + virtual sal_Int32 SAL_CALL endOfSentence( const OUString& rText, sal_Int32, + const lang::Locale& ) override + { return rText.getLength(); } + + virtual i18n::LineBreakResults SAL_CALL getLineBreak( const OUString&, sal_Int32, + const lang::Locale&, sal_Int32, + const i18n::LineBreakHyphenationOptions&, + const i18n::LineBreakUserOptions&) override + { + return i18n::LineBreakResults(); + } + + virtual sal_Int16 SAL_CALL getScriptType( const OUString&, sal_Int32 ) override { return -1; } + virtual sal_Int32 SAL_CALL beginOfScript( const OUString&, sal_Int32, + sal_Int16 ) override { return -1; } + virtual sal_Int32 SAL_CALL endOfScript( const OUString&, sal_Int32, + sal_Int16 ) override { return -1; } + virtual sal_Int32 SAL_CALL previousScript( const OUString&, sal_Int32, + sal_Int16 ) override { return -1; } + virtual sal_Int32 SAL_CALL nextScript( const OUString&, sal_Int32, + sal_Int16 ) override { return -1; } + + virtual sal_Int32 SAL_CALL beginOfCharBlock( const OUString&, sal_Int32, + const lang::Locale&, sal_Int16 ) override { return -1; } + virtual sal_Int32 SAL_CALL endOfCharBlock( const OUString& rText, sal_Int32 nStartPos, + const lang::Locale&, sal_Int16 CharType ) override + { + const sal_Unicode *pStr = rText.getStr()+nStartPos; + for (sal_Int32 nI = nStartPos; nI < rText.getLength(); ++nI) + { + if (CharType == i18n::CharType::DECIMAL_DIGIT_NUMBER && !IS_DIGIT(*pStr)) + return nI; + else if (CharType != i18n::CharType::DECIMAL_DIGIT_NUMBER && IS_DIGIT(*pStr)) + return nI; + ++pStr; + } + return -1; + } + virtual sal_Int32 SAL_CALL previousCharBlock( const OUString&, sal_Int32, + const lang::Locale&, sal_Int16 ) override { return -1; } + virtual sal_Int32 SAL_CALL nextCharBlock( const OUString& rText, sal_Int32 nStartPos, + const lang::Locale&, sal_Int16 CharType ) override + { + const sal_Unicode *pStr = rText.getStr()+nStartPos; + for (sal_Int32 nI = nStartPos; nI < rText.getLength(); ++nI) + { + if (CharType == i18n::CharType::DECIMAL_DIGIT_NUMBER && IS_DIGIT(*pStr)) + return nI; + else if (CharType != i18n::CharType::DECIMAL_DIGIT_NUMBER && !IS_DIGIT(*pStr)) + return nI; + ++pStr; + } + return -1; + } +}; + +void TestString::testNatural() +{ + using namespace comphelper::string; + + uno::Reference< i18n::XCollator > xCollator(new testCollator); + uno::Reference< i18n::XBreakIterator > xBI(new testBreakIterator); + +// --- Some generic tests to ensure we do not alter original behavior +// outside what we want + CPPUNIT_ASSERT_EQUAL( + static_cast<sal_Int32>(0), compareNatural("ABC", "ABC", xCollator, xBI, lang::Locale()) + ); + // Case sensitivity + CPPUNIT_ASSERT( + compareNatural("ABC", "abc", xCollator, xBI, lang::Locale()) < 0 + ); + // Reverse + CPPUNIT_ASSERT( + compareNatural("abc", "ABC", xCollator, xBI, lang::Locale()) > 0 + ); + // First shorter + CPPUNIT_ASSERT( + compareNatural("alongstring", "alongerstring", xCollator, xBI, lang::Locale()) > 0 + ); + // Second shorter + CPPUNIT_ASSERT( + compareNatural("alongerstring", "alongstring", xCollator, xBI, lang::Locale()) < 0 + ); +// -- Here we go on natural order, each one is followed by classic compare and the reverse comparison + // That's why we originally made the patch + CPPUNIT_ASSERT( + compareNatural("Heading 9", "Heading 10", xCollator, xBI, lang::Locale()) < 0 + ); + // Original behavior + CPPUNIT_ASSERT( + OUString("Heading 9").compareTo("Heading 10") > 0 + ); + CPPUNIT_ASSERT( + compareNatural("Heading 10", "Heading 9", xCollator, xBI, lang::Locale()) > 0 + ); + // Harder + CPPUNIT_ASSERT( + compareNatural("July, the 4th", "July, the 10th", xCollator, xBI, lang::Locale()) < 0 + ); + CPPUNIT_ASSERT( + OUString("July, the 4th").compareTo("July, the 10th") > 0 + ); + CPPUNIT_ASSERT( + compareNatural("July, the 10th", "July, the 4th", xCollator, xBI, lang::Locale()) > 0 + ); + // Hardest + CPPUNIT_ASSERT( + compareNatural("abc08", "abc010", xCollator, xBI, lang::Locale()) < 0 + ); + CPPUNIT_ASSERT( + OUString("abc08").compareTo("abc010") > 0 + ); + CPPUNIT_ASSERT( + compareNatural("abc010", "abc08", xCollator, xBI, lang::Locale()) > 0 + ); + CPPUNIT_ASSERT_EQUAL( + static_cast<sal_Int32>(0), compareNatural("apple10apple", "apple10apple", xCollator, xBI, lang::Locale()) + ); +} + +void TestString::testStripStart() +{ + OString aIn("abc"); + OString aOut; + + aOut = ::comphelper::string::stripStart(aIn, 'b'); + CPPUNIT_ASSERT_EQUAL(OString("abc"), aOut); + + aOut = ::comphelper::string::stripStart(aIn, 'a'); + CPPUNIT_ASSERT_EQUAL(OString("bc"), aOut); + + aIn = "aaa"; + aOut = ::comphelper::string::stripStart(aIn, 'a'); + CPPUNIT_ASSERT(aOut.isEmpty()); + + aIn = "aba"; + aOut = ::comphelper::string::stripStart(aIn, 'a'); + CPPUNIT_ASSERT_EQUAL(OString("ba"), aOut); +} + +void TestString::testStripEnd() +{ + OString aIn("abc"); + OString aOut; + + aOut = ::comphelper::string::stripEnd(aIn, 'b'); + CPPUNIT_ASSERT_EQUAL(OString("abc"), aOut); + + aOut = ::comphelper::string::stripEnd(aIn, 'c'); + CPPUNIT_ASSERT_EQUAL(OString("ab"), aOut); + + aIn = "aaa"; + aOut = ::comphelper::string::stripEnd(aIn, 'a'); + CPPUNIT_ASSERT(aOut.isEmpty()); + + aIn = "aba"; + aOut = ::comphelper::string::stripEnd(aIn, 'a'); + CPPUNIT_ASSERT_EQUAL(OString("ab"), aOut); +} + +void TestString::testStrip() +{ + OString aIn("abc"); + OString aOut; + + aOut = ::comphelper::string::strip(aIn, 'b'); + CPPUNIT_ASSERT_EQUAL(OString("abc"), aOut); + + aOut = ::comphelper::string::strip(aIn, 'c'); + CPPUNIT_ASSERT_EQUAL(OString("ab"), aOut); + + aIn = "aaa"; + aOut = ::comphelper::string::strip(aIn, 'a'); + CPPUNIT_ASSERT(aOut.isEmpty()); + + aIn = "aba"; + aOut = ::comphelper::string::strip(aIn, 'a'); + CPPUNIT_ASSERT_EQUAL(OString("b"), aOut); +} + +void TestString::testToken() +{ + OString aIn("10.11.12"); + OString aOut; + + aOut = aIn.getToken(-1, '.'); + CPPUNIT_ASSERT(aOut.isEmpty()); + + aOut = aIn.getToken(0, '.'); + CPPUNIT_ASSERT_EQUAL(OString("10"), aOut); + + aOut = aIn.getToken(1, '.'); + CPPUNIT_ASSERT_EQUAL(OString("11"), aOut); + + aOut = aIn.getToken(2, '.'); + CPPUNIT_ASSERT_EQUAL(OString("12"), aOut); + + aOut = aIn.getToken(3, '.'); + CPPUNIT_ASSERT(aOut.isEmpty()); +} + +void TestString::testTokenCount() +{ + OString aIn("10.11.12"); + sal_Int32 nOut; + + nOut = ::comphelper::string::getTokenCount(aIn, '.'); + CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32>(3), nOut); + + nOut = ::comphelper::string::getTokenCount(aIn, 'X'); + CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32>(1), nOut); + + nOut = ::comphelper::string::getTokenCount(OString(), 'X'); + CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32>(0), nOut); +} + +void TestString::testReverseString() +{ + OString aIn("ABC"); + OString aOut = ::comphelper::string::reverseString(aIn); + + CPPUNIT_ASSERT_EQUAL(OString("CBA"), aOut); +} + +void TestString::testSplit() +{ + OUString aIn("CTRL+ALT+F1"); + std::vector<OUString> aRet = ::comphelper::string::split(aIn, '+'); + CPPUNIT_ASSERT_EQUAL(size_t(3), aRet.size()); + CPPUNIT_ASSERT_EQUAL(OUString("CTRL"), aRet[0]); + CPPUNIT_ASSERT_EQUAL(OUString("ALT"), aRet[1]); + CPPUNIT_ASSERT_EQUAL(OUString("F1"), aRet[2]); +} + +void TestString::testRemoveAny() +{ + using namespace ::comphelper::string; + OUString in("abcAAAbbC"); + sal_Unicode const test1 [] = { 'a', 0 }; + CPPUNIT_ASSERT_EQUAL(OUString("bcAAAbbC"), removeAny(in, test1)); + sal_Unicode const test2 [] = { 0 }; + CPPUNIT_ASSERT_EQUAL(in, removeAny(in, test2)); + sal_Unicode const test3 [] = { 'A', 0 }; + CPPUNIT_ASSERT_EQUAL(OUString("abcbbC"), removeAny(in, test3)); + sal_Unicode const test4 [] = { 'A', 'a', 0 }; + CPPUNIT_ASSERT_EQUAL(OUString("bcbbC"), removeAny(in, test4)); + sal_Unicode const test5 [] = { 'C', 0 }; + CPPUNIT_ASSERT_EQUAL(OUString("abcAAAbb"), removeAny(in, test5)); + sal_Unicode const test6 [] = { 'X', 0 }; + CPPUNIT_ASSERT_EQUAL(in, removeAny(in, test6)); + sal_Unicode const test7 [] = { 'A', 'B', 'C', 'a', 'b', 'c', 0 }; + CPPUNIT_ASSERT_EQUAL(OUString(), removeAny(in, test7)); +} + +CPPUNIT_TEST_SUITE_REGISTRATION(TestString); + +} + +CPPUNIT_PLUGIN_IMPLEMENT(); + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/comphelper/qa/unit/base64_test.cxx b/comphelper/qa/unit/base64_test.cxx new file mode 100644 index 000000000..97f7b78aa --- /dev/null +++ b/comphelper/qa/unit/base64_test.cxx @@ -0,0 +1,111 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * 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 . + */ + +#include <sal/types.h> +#include <cppunit/TestAssert.h> +#include <cppunit/TestFixture.h> +#include <cppunit/extensions/HelperMacros.h> + +#include <rtl/ustrbuf.hxx> + +#include <com/sun/star/uno/Sequence.hxx> + +#include <comphelper/base64.hxx> + +using namespace css; + +namespace { + +class Base64Test : public CppUnit::TestFixture +{ +public: + + void testBase64Encode(); + void testBase64Decode(); + void testBase64EncodeForOStringBuffer(); + + CPPUNIT_TEST_SUITE(Base64Test); + CPPUNIT_TEST(testBase64Encode); + CPPUNIT_TEST(testBase64Decode); + CPPUNIT_TEST(testBase64EncodeForOStringBuffer); + CPPUNIT_TEST_SUITE_END(); +}; + +void Base64Test::testBase64Encode() +{ + OUStringBuffer aBuffer(32); + uno::Sequence<sal_Int8> inputSequence; + + inputSequence = { 0, 0, 0, 0, 0, 1, 2, 3 }; + comphelper::Base64::encode(aBuffer, inputSequence); + CPPUNIT_ASSERT_EQUAL(OUString("AAAAAAABAgM="), aBuffer.toString()); + aBuffer.setLength(0); + + inputSequence = { 5, 2, 3, 0, 0, 1, 2, 3 }; + comphelper::Base64::encode(aBuffer, inputSequence); + CPPUNIT_ASSERT_EQUAL(OUString("BQIDAAABAgM="), aBuffer.toString()); + aBuffer.setLength(0); + + inputSequence = { sal_Int8(sal_uInt8(200)), 31, 77, 111, 0, 1, 2, 3 }; + comphelper::Base64::encode(aBuffer, inputSequence); + CPPUNIT_ASSERT_EQUAL(OUString("yB9NbwABAgM="), aBuffer.makeStringAndClear()); +} + +void Base64Test::testBase64Decode() +{ + uno::Sequence<sal_Int8> decodedSequence; + + uno::Sequence<sal_Int8> expectedSequence = { 0, 0, 0, 0, 0, 1, 2, 3 }; + comphelper::Base64::decode(decodedSequence, "AAAAAAABAgM="); + CPPUNIT_ASSERT(std::equal(expectedSequence.begin(), expectedSequence.end(), decodedSequence.begin())); + + expectedSequence = { 5, 2, 3, 0, 0, 1, 2, 3 }; + comphelper::Base64::decode(decodedSequence, "BQIDAAABAgM="); + CPPUNIT_ASSERT(std::equal(expectedSequence.begin(), expectedSequence.end(), decodedSequence.begin())); + + expectedSequence = { sal_Int8(sal_uInt8(200)), 31, 77, 111, 0, 1, 2, 3 }; + comphelper::Base64::decode(decodedSequence, "yB9NbwABAgM="); + CPPUNIT_ASSERT(std::equal(expectedSequence.begin(), expectedSequence.end(), decodedSequence.begin())); +} + +void Base64Test::testBase64EncodeForOStringBuffer() +{ + OStringBuffer aBuffer(32); + uno::Sequence<sal_Int8> inputSequence; + + inputSequence = { 0, 0, 0, 0, 0, 1, 2, 3 }; + comphelper::Base64::encode(aBuffer, inputSequence); + CPPUNIT_ASSERT_EQUAL(OString("AAAAAAABAgM="), aBuffer.toString()); + aBuffer.setLength(0); + + inputSequence = { 5, 2, 3, 0, 0, 1, 2, 3 }; + comphelper::Base64::encode(aBuffer, inputSequence); + CPPUNIT_ASSERT_EQUAL(OString("BQIDAAABAgM="), aBuffer.toString()); + aBuffer.setLength(0); + + inputSequence = { sal_Int8(sal_uInt8(200)), 31, 77, 111, 0, 1, 2, 3 }; + comphelper::Base64::encode(aBuffer, inputSequence); + CPPUNIT_ASSERT_EQUAL(OString("yB9NbwABAgM="), aBuffer.makeStringAndClear()); +} + +CPPUNIT_TEST_SUITE_REGISTRATION(Base64Test); + +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/comphelper/qa/unit/parallelsorttest.cxx b/comphelper/qa/unit/parallelsorttest.cxx new file mode 100644 index 000000000..90dcb3c23 --- /dev/null +++ b/comphelper/qa/unit/parallelsorttest.cxx @@ -0,0 +1,101 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include <comphelper/parallelsort.hxx> +#include <comphelper/threadpool.hxx> +#include <rtl/string.hxx> +#include <cppunit/TestAssert.h> +#include <cppunit/TestFixture.h> +#include <cppunit/extensions/HelperMacros.h> +#include <cppunit/plugin/TestPlugIn.h> + +#include <cstdlib> +#include <vector> +#include <algorithm> +#include <random> + +class ParallelSortTest : public CppUnit::TestFixture +{ +public: + void testSortTiny(); + void testSortMedium(); + void testSortBig(); + + virtual void setUp() override; + virtual void tearDown() override; + + CPPUNIT_TEST_SUITE(ParallelSortTest); + CPPUNIT_TEST(testSortTiny); + CPPUNIT_TEST(testSortMedium); + CPPUNIT_TEST(testSortBig); + CPPUNIT_TEST_SUITE_END(); + +private: + void sortTest(size_t nLen); + void fillRandomUptoN(std::vector<size_t>& rVector, size_t N); + + comphelper::ThreadPool* pThreadPool; + size_t mnThreads; +}; + +void ParallelSortTest::setUp() +{ + pThreadPool = &comphelper::ThreadPool::getSharedOptimalPool(); + mnThreads = pThreadPool->getWorkerCount(); +} + +void ParallelSortTest::tearDown() +{ + if (pThreadPool) + pThreadPool->joinAll(); +} + +void ParallelSortTest::fillRandomUptoN(std::vector<size_t>& rVector, size_t N) +{ + rVector.resize(N); + for (size_t nIdx = 0; nIdx < N; ++nIdx) + rVector[nIdx] = nIdx; + std::shuffle(rVector.begin(), rVector.end(), std::default_random_engine(42)); +} + +void ParallelSortTest::sortTest(size_t nLen) +{ + std::vector<size_t> aVector(nLen); + fillRandomUptoN(aVector, nLen); + comphelper::parallelSort(aVector.begin(), aVector.end()); + for (size_t nIdx = 0; nIdx < nLen; ++nIdx) + { + OString aMsg = "Wrong aVector[" + OString::number(nIdx) + "]"; + CPPUNIT_ASSERT_EQUAL_MESSAGE(aMsg.getStr(), nIdx, aVector[nIdx]); + } +} + +void ParallelSortTest::testSortTiny() +{ + sortTest(5); + sortTest(15); + sortTest(16); + sortTest(17); +} + +void ParallelSortTest::testSortMedium() +{ + sortTest(1025); + sortTest(1029); + sortTest(1024 * 2 + 1); + sortTest(1024 * 2 + 9); +} + +void ParallelSortTest::testSortBig() { sortTest(1024 * 16 + 3); } + +CPPUNIT_TEST_SUITE_REGISTRATION(ParallelSortTest); + +CPPUNIT_PLUGIN_IMPLEMENT(); + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/comphelper/qa/unit/syntaxhighlighttest.cxx b/comphelper/qa/unit/syntaxhighlighttest.cxx new file mode 100644 index 000000000..8a5b66ed2 --- /dev/null +++ b/comphelper/qa/unit/syntaxhighlighttest.cxx @@ -0,0 +1,122 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include <comphelper/syntaxhighlight.hxx> +#include <cppunit/TestAssert.h> +#include <cppunit/TestFixture.h> +#include <cppunit/extensions/HelperMacros.h> +#include <cppunit/plugin/TestPlugIn.h> +#include <rtl/ustring.hxx> + +#include <vector> + +class SyntaxHighlightTest : public CppUnit::TestFixture +{ +public: + void testBasicString(); + void testBasicComment(); + void testBasicCommentNewline(); + void testBasicEmptyComment(); + void testBasicEmptyCommentNewline(); + void testBasic(); + + CPPUNIT_TEST_SUITE(SyntaxHighlightTest); + CPPUNIT_TEST(testBasicString); + CPPUNIT_TEST(testBasicComment); + CPPUNIT_TEST(testBasicCommentNewline); + CPPUNIT_TEST(testBasicEmptyComment); + CPPUNIT_TEST(testBasicEmptyCommentNewline); + CPPUNIT_TEST(testBasic); + CPPUNIT_TEST_SUITE_END(); +}; + +void SyntaxHighlightTest::testBasicString() { + OUString s("\"foo\""); + std::vector<HighlightPortion> ps; + SyntaxHighlighter(HighlighterLanguage::Basic).getHighlightPortions(s, ps); + CPPUNIT_ASSERT_EQUAL( + static_cast<std::vector<HighlightPortion>::size_type>(1), ps.size()); + CPPUNIT_ASSERT_EQUAL(sal_Int32(0), ps[0].nBegin); + CPPUNIT_ASSERT_EQUAL(sal_Int32(5), ps[0].nEnd); + CPPUNIT_ASSERT_EQUAL(TokenType::String, ps[0].tokenType); +} + +void SyntaxHighlightTest::testBasicComment() { + OUString s("' foo"); + std::vector<HighlightPortion> ps; + SyntaxHighlighter(HighlighterLanguage::Basic).getHighlightPortions(s, ps); + CPPUNIT_ASSERT_EQUAL( + static_cast<std::vector<HighlightPortion>::size_type>(1), ps.size()); + CPPUNIT_ASSERT_EQUAL(sal_Int32(0), ps[0].nBegin); + CPPUNIT_ASSERT_EQUAL(sal_Int32(5), ps[0].nEnd); + CPPUNIT_ASSERT_EQUAL(TokenType::Comment, ps[0].tokenType); +} + +void SyntaxHighlightTest::testBasicCommentNewline() { + OUString s("' foo\n"); + std::vector<HighlightPortion> ps; + SyntaxHighlighter(HighlighterLanguage::Basic).getHighlightPortions(s, ps); + CPPUNIT_ASSERT_EQUAL( + static_cast<std::vector<HighlightPortion>::size_type>(2), ps.size()); + CPPUNIT_ASSERT_EQUAL(sal_Int32(0), ps[0].nBegin); + CPPUNIT_ASSERT_EQUAL(sal_Int32(5), ps[0].nEnd); + CPPUNIT_ASSERT_EQUAL(TokenType::Comment, ps[0].tokenType); + CPPUNIT_ASSERT_EQUAL(sal_Int32(5), ps[1].nBegin); + CPPUNIT_ASSERT_EQUAL(sal_Int32(6), ps[1].nEnd); + CPPUNIT_ASSERT_EQUAL(TokenType::EOL, ps[1].tokenType); +} + +void SyntaxHighlightTest::testBasicEmptyComment() { + OUString s("'"); + std::vector<HighlightPortion> ps; + SyntaxHighlighter(HighlighterLanguage::Basic).getHighlightPortions(s, ps); + CPPUNIT_ASSERT_EQUAL( + static_cast<std::vector<HighlightPortion>::size_type>(1), ps.size()); + CPPUNIT_ASSERT_EQUAL(sal_Int32(0), ps[0].nBegin); + CPPUNIT_ASSERT_EQUAL(sal_Int32(1), ps[0].nEnd); + CPPUNIT_ASSERT_EQUAL(TokenType::Comment, ps[0].tokenType); +} + +void SyntaxHighlightTest::testBasicEmptyCommentNewline() { + OUString s("'\n"); + std::vector<HighlightPortion> ps; + SyntaxHighlighter(HighlighterLanguage::Basic).getHighlightPortions(s, ps); + CPPUNIT_ASSERT_EQUAL( + static_cast<std::vector<HighlightPortion>::size_type>(2), ps.size()); + CPPUNIT_ASSERT_EQUAL(sal_Int32(0), ps[0].nBegin); + CPPUNIT_ASSERT_EQUAL(sal_Int32(1), ps[0].nEnd); + CPPUNIT_ASSERT_EQUAL(TokenType::Comment, ps[0].tokenType); + CPPUNIT_ASSERT_EQUAL(sal_Int32(1), ps[1].nBegin); + CPPUNIT_ASSERT_EQUAL(sal_Int32(2), ps[1].nEnd); + CPPUNIT_ASSERT_EQUAL(TokenType::EOL, ps[1].tokenType); +} + +void SyntaxHighlightTest::testBasic() +{ + OUString aBasicString(" if Mid(sText,iRun,1 )<> \" \" then Mid( sText ,iRun, 1, Chr( 1 + Asc( Mid(sText,iRun,1 )) ) '"); + + std::vector<HighlightPortion> aPortions; + SyntaxHighlighter(HighlighterLanguage::Basic).getHighlightPortions( + aBasicString, aPortions ); + + sal_Int32 prevEnd = 0; + for (auto const& portion : aPortions) + { + CPPUNIT_ASSERT_EQUAL(prevEnd, portion.nBegin); + CPPUNIT_ASSERT(portion.nBegin < portion.nEnd); + prevEnd = portion.nEnd; + } + CPPUNIT_ASSERT_EQUAL(aBasicString.getLength(), prevEnd); +} + +CPPUNIT_TEST_SUITE_REGISTRATION(SyntaxHighlightTest); + +CPPUNIT_PLUGIN_IMPLEMENT(); + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/comphelper/qa/unit/test_guards.cxx b/comphelper/qa/unit/test_guards.cxx new file mode 100644 index 000000000..1d2b5f209 --- /dev/null +++ b/comphelper/qa/unit/test_guards.cxx @@ -0,0 +1,57 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include <sal/types.h> +#include <comphelper/flagguard.hxx> +#include <unotest/bootstrapfixturebase.hxx> + +CPPUNIT_TEST_FIXTURE(CppUnit::TestFixture, test_comphelperGuards) +{ + bool bFlag = true; + { + // Test that comphelper::ScopeGuard executes its parameter on destruction + comphelper::ScopeGuard aGuard([&bFlag] { bFlag = false; }); + CPPUNIT_ASSERT(bFlag); + } + CPPUNIT_ASSERT(!bFlag); + + { + // Test that comphelper::FlagGuard properly sets and resets the flag + comphelper::FlagGuard aGuard(bFlag); + CPPUNIT_ASSERT(bFlag); + } + CPPUNIT_ASSERT(!bFlag); + + bFlag = true; + { + // Test that comphelper::FlagGuard properly sets and resets the flag + comphelper::FlagGuard aGuard(bFlag); + CPPUNIT_ASSERT(bFlag); + } + // comphelper::FlagGuard must reset flag to false on destruction unconditionally + CPPUNIT_ASSERT(!bFlag); + + { + // Test that comphelper::FlagRestorationGuard properly sets and resets the flag + comphelper::FlagRestorationGuard aGuard(bFlag, true); + CPPUNIT_ASSERT(bFlag); + } + CPPUNIT_ASSERT(!bFlag); + + bFlag = true; + { + // Test that comphelper::FlagRestorationGuard properly sets and resets the flag + comphelper::FlagRestorationGuard aGuard(bFlag, false); + CPPUNIT_ASSERT(!bFlag); + } + // comphelper::FlagRestorationGuard must reset flag to initial state on destruction + CPPUNIT_ASSERT(bFlag); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/comphelper/qa/unit/test_hash.cxx b/comphelper/qa/unit/test_hash.cxx new file mode 100644 index 000000000..99ce5bfd1 --- /dev/null +++ b/comphelper/qa/unit/test_hash.cxx @@ -0,0 +1,134 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include <sal/config.h> +#include <config_oox.h> +#include <comphelper/hash.hxx> +#include <comphelper/docpasswordhelper.hxx> + +#include <rtl/ustring.hxx> +#include <iomanip> + +#include <cppunit/TestFixture.h> +#include <cppunit/extensions/HelperMacros.h> + +#if USE_TLS_NSS +#include <nss.h> +#endif + +class TestHash : public CppUnit::TestFixture +{ +public: + void testMD5(); + void testSHA1(); + void testSHA256(); + void testSHA512(); + void testSHA512_NoSaltNoSpin(); + void testSHA512_saltspin(); + + virtual void tearDown() + { +#if USE_TLS_NSS + NSS_Shutdown(); +#endif + } + CPPUNIT_TEST_SUITE(TestHash); + CPPUNIT_TEST(testMD5); + CPPUNIT_TEST(testSHA1); + CPPUNIT_TEST(testSHA256); + CPPUNIT_TEST(testSHA512); + CPPUNIT_TEST(testSHA512_NoSaltNoSpin); + CPPUNIT_TEST(testSHA512_saltspin); + CPPUNIT_TEST_SUITE_END(); +}; + +namespace { + +std::string tostring(const std::vector<unsigned char>& a) +{ + std::stringstream aStrm; + for (auto& i:a) + { + aStrm << std::setw(2) << std::setfill('0') << std::hex << static_cast<int>(i); + } + + return aStrm.str(); +} + +} + +void TestHash::testMD5() +{ + comphelper::Hash aHash(comphelper::HashType::MD5); + const char* const pInput = ""; + aHash.update(reinterpret_cast<const unsigned char*>(pInput), 0); + std::vector<unsigned char> calculate_hash = aHash.finalize(); + CPPUNIT_ASSERT_EQUAL(size_t(16), calculate_hash.size()); + CPPUNIT_ASSERT_EQUAL(std::string("d41d8cd98f00b204e9800998ecf8427e"), tostring(calculate_hash)); +} + +void TestHash::testSHA1() +{ + comphelper::Hash aHash(comphelper::HashType::SHA1); + const char* const pInput = ""; + aHash.update(reinterpret_cast<const unsigned char*>(pInput), 0); + std::vector<unsigned char> calculate_hash = aHash.finalize(); + CPPUNIT_ASSERT_EQUAL(size_t(20), calculate_hash.size()); + CPPUNIT_ASSERT_EQUAL(std::string("da39a3ee5e6b4b0d3255bfef95601890afd80709"), tostring(calculate_hash)); +} + +void TestHash::testSHA256() +{ + comphelper::Hash aHash(comphelper::HashType::SHA256); + const char* const pInput = ""; + aHash.update(reinterpret_cast<const unsigned char*>(pInput), 0); + std::vector<unsigned char> calculate_hash = aHash.finalize(); + CPPUNIT_ASSERT_EQUAL(size_t(32), calculate_hash.size()); + CPPUNIT_ASSERT_EQUAL(std::string("e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"), tostring(calculate_hash)); +} + +void TestHash::testSHA512() +{ + comphelper::Hash aHash(comphelper::HashType::SHA512); + const char* const pInput = ""; + aHash.update(reinterpret_cast<const unsigned char*>(pInput), 0); + std::vector<unsigned char> calculate_hash = aHash.finalize(); + CPPUNIT_ASSERT_EQUAL(size_t(64), calculate_hash.size()); + std::string aStr("cf83e1357eefb8bdf1542850d66d8007d620e4050b5715dc83f4a921d36ce9ce47d0d13c5d85f2b0ff8318d2877eec2f63b931bd47417a81a538327af927da3e"); + CPPUNIT_ASSERT_EQUAL(aStr, tostring(calculate_hash)); +} + +// Must be identical to testSHA512() +void TestHash::testSHA512_NoSaltNoSpin() +{ + const char* const pInput = ""; + std::vector<unsigned char> calculate_hash = + comphelper::Hash::calculateHash( reinterpret_cast<const unsigned char*>(pInput), 0, + nullptr, 0, 0, comphelper::Hash::IterCount::NONE, comphelper::HashType::SHA512); + CPPUNIT_ASSERT_EQUAL(size_t(64), calculate_hash.size()); + std::string aStr("cf83e1357eefb8bdf1542850d66d8007d620e4050b5715dc83f4a921d36ce9ce47d0d13c5d85f2b0ff8318d2877eec2f63b931bd47417a81a538327af927da3e"); + CPPUNIT_ASSERT_EQUAL(aStr, tostring(calculate_hash)); +} + +// Password, salt, hash and spin count taken from OOXML sheetProtection of +// tdf#104250 https://bugs.documentfoundation.org/attachment.cgi?id=129104 +void TestHash::testSHA512_saltspin() +{ + const OUString aPass("pwd"); + const OUString aAlgo("SHA-512"); + const OUString aSalt("876MLoKTq42+/DLp415iZQ=="); + const OUString aHash = comphelper::DocPasswordHelper::GetOoxHashAsBase64( aPass, aSalt, 100000, + comphelper::Hash::IterCount::APPEND, aAlgo); + const OUString aStr("5l3mgNHXpWiFaBPv5Yso1Xd/UifWvQWmlDnl/hsCYbFT2sJCzorjRmBCQ/3qeDu6Q/4+GIE8a1DsdaTwYh1q2g=="); + CPPUNIT_ASSERT_EQUAL(aStr, aHash); +} + +CPPUNIT_TEST_SUITE_REGISTRATION(TestHash); + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/comphelper/qa/unit/threadpooltest.cxx b/comphelper/qa/unit/threadpooltest.cxx new file mode 100644 index 000000000..10fb90c30 --- /dev/null +++ b/comphelper/qa/unit/threadpooltest.cxx @@ -0,0 +1,55 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include <comphelper/threadpool.hxx> +#include <cppunit/TestAssert.h> +#include <cppunit/TestFixture.h> +#include <cppunit/extensions/HelperMacros.h> +#include <cppunit/plugin/TestPlugIn.h> + +#include <stdlib.h> +#include <thread> + +class ThreadPoolTest : public CppUnit::TestFixture +{ +public: + void testPreferredConcurrency(); + + CPPUNIT_TEST_SUITE(ThreadPoolTest); + CPPUNIT_TEST(testPreferredConcurrency); + CPPUNIT_TEST_SUITE_END(); +}; + +void ThreadPoolTest::testPreferredConcurrency() +{ + // Check default. + auto nThreads = comphelper::ThreadPool::getPreferredConcurrency(); + sal_Int32 nExpected = 4; // UTs are capped to 4. + CPPUNIT_ASSERT_MESSAGE("Expected no more than 4 threads", nExpected >= nThreads); + +#ifndef _WIN32 + // The result should be cached, so this should change anything. + nThreads = std::thread::hardware_concurrency() * 2; + setenv("MAX_CONCURRENCY", std::to_string(nThreads).c_str(), true); + nThreads = comphelper::ThreadPool::getPreferredConcurrency(); + CPPUNIT_ASSERT_MESSAGE("Expected no more than hardware threads", + nThreads <= static_cast<sal_Int32>(std::thread::hardware_concurrency())); + + // Revert and check. Again, nothing should change. + unsetenv("MAX_CONCURRENCY"); + nThreads = comphelper::ThreadPool::getPreferredConcurrency(); + CPPUNIT_ASSERT_MESSAGE("Expected no more than 4 threads", nExpected >= nThreads); +#endif +} + +CPPUNIT_TEST_SUITE_REGISTRATION(ThreadPoolTest); + +CPPUNIT_PLUGIN_IMPLEMENT(); + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/comphelper/qa/unit/types_test.cxx b/comphelper/qa/unit/types_test.cxx new file mode 100644 index 000000000..89ad6cae8 --- /dev/null +++ b/comphelper/qa/unit/types_test.cxx @@ -0,0 +1,97 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include <comphelper/types.hxx> +#include <sal/types.h> + +#include <cppunit/TestAssert.h> +#include <cppunit/TestFixture.h> +#include <cppunit/extensions/HelperMacros.h> +#include <cppunit/plugin/TestPlugIn.h> + +using namespace css; + +namespace +{ +class TypesTest : public CppUnit::TestFixture +{ +public: + void testGetINT64(); + void testGetINT32(); + void testGetINT16(); + void testGetDouble(); + void testGetFloat(); + void testGetString(); + + CPPUNIT_TEST_SUITE(TypesTest); + + CPPUNIT_TEST(testGetINT64); + CPPUNIT_TEST(testGetINT32); + CPPUNIT_TEST(testGetINT16); + CPPUNIT_TEST(testGetDouble); + CPPUNIT_TEST(testGetFloat); + CPPUNIT_TEST(testGetString); + + CPPUNIT_TEST_SUITE_END(); +}; + +void TypesTest::testGetINT64() +{ + CPPUNIT_ASSERT_EQUAL(sal_Int64(1337), ::comphelper::getINT64(uno::makeAny(sal_Int64(1337)))); + + uno::Any aValue; + CPPUNIT_ASSERT_EQUAL(sal_Int64(0), ::comphelper::getINT64(aValue)); +} + +void TypesTest::testGetINT32() +{ + CPPUNIT_ASSERT_EQUAL(sal_Int32(1337), ::comphelper::getINT32(uno::makeAny(sal_Int32(1337)))); + + uno::Any aValue; + CPPUNIT_ASSERT_EQUAL(sal_Int32(0), ::comphelper::getINT32(aValue)); +} + +void TypesTest::testGetINT16() +{ + CPPUNIT_ASSERT_EQUAL(sal_Int16(1337), ::comphelper::getINT16(uno::makeAny(sal_Int16(1337)))); + + uno::Any aValue; + CPPUNIT_ASSERT_EQUAL(sal_Int16(0), ::comphelper::getINT16(aValue)); +} + +void TypesTest::testGetDouble() +{ + CPPUNIT_ASSERT_EQUAL(1337.1337, ::comphelper::getDouble(uno::makeAny(1337.1337))); + + uno::Any aValue; + CPPUNIT_ASSERT_EQUAL(0.0, ::comphelper::getDouble(aValue)); +} + +void TypesTest::testGetFloat() +{ + CPPUNIT_ASSERT_EQUAL(static_cast<float>(1337.0), + ::comphelper::getFloat(uno::makeAny(static_cast<float>(1337.0)))); + + uno::Any aValue; + CPPUNIT_ASSERT_EQUAL(static_cast<float>(0.0), ::comphelper::getFloat(aValue)); +} + +void TypesTest::testGetString() +{ + CPPUNIT_ASSERT_EQUAL(OUString("1337"), ::comphelper::getString(uno::makeAny(OUString("1337")))); + + uno::Any aValue; + CPPUNIT_ASSERT_EQUAL(OUString(""), ::comphelper::getString(aValue)); +} + +CPPUNIT_TEST_SUITE_REGISTRATION(TypesTest); + +} // namespace + +/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/comphelper/qa/unit/variadictemplates.cxx b/comphelper/qa/unit/variadictemplates.cxx new file mode 100644 index 000000000..c894cf1a7 --- /dev/null +++ b/comphelper/qa/unit/variadictemplates.cxx @@ -0,0 +1,181 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include <optional> +#include <sal/types.h> +#include <comphelper/unwrapargs.hxx> +#include <cppunit/TestAssert.h> +#include <cppunit/TestFixture.h> +#include <cppunit/extensions/HelperMacros.h> +#include <cppunit/plugin/TestPlugIn.h> + +#include <sstream> + +class VariadicTemplatesTest : public CppUnit::TestFixture +{ +public: + void testUnwrapArgs(); + + CPPUNIT_TEST_SUITE(VariadicTemplatesTest); + CPPUNIT_TEST(testUnwrapArgs); + CPPUNIT_TEST_SUITE_END(); +}; + +namespace { + +namespace detail { + +template <typename T> +void extract( + ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Any> const& seq, + sal_Int32 nArg, T & v, + ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface> + const& xErrorContext ) +{ + if (nArg >= seq.getLength()) { + throw ::com::sun::star::lang::IllegalArgumentException( + "No such argument available!", + xErrorContext, static_cast<sal_Int16>(nArg) ); + } + if (! fromAny(seq[nArg], &v)) { + throw ::com::sun::star::lang::IllegalArgumentException( + "Cannot extract ANY { " + + seq[nArg].getValueType().getTypeName() + + " } to " + ::cppu::UnoType<T>::get().getTypeName(), + xErrorContext, + static_cast<sal_Int16>(nArg) ); + } +} + +template <typename T> +void extract( + ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Any> const& seq, + sal_Int32 nArg, ::std::optional<T> & v, + ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface> + const& xErrorContext ) +{ + if (nArg < seq.getLength()) { + T t; + extract( seq, nArg, t, xErrorContext ); + v = t; + } +} + +} // namespace detail + +template < typename T0, typename T1, typename T2, typename T3, typename T4 > +void unwrapArgsBaseline( + ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Any > const& seq, + T0& v0, T1& v1, T2& v2, T3& v3, T4& v4, + ::com::sun::star::uno::Reference< + ::com::sun::star::uno::XInterface> const& xErrorContext = + ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface>() ) +{ + ::detail::extract( seq, 0, v0, xErrorContext ); + ::detail::extract( seq, 1, v1, xErrorContext ); + ::detail::extract( seq, 2, v2, xErrorContext ); + ::detail::extract( seq, 3, v3, xErrorContext ); + ::detail::extract( seq, 4, v4, xErrorContext ); +} + +} + +void VariadicTemplatesTest::testUnwrapArgs() { + OUString tmp1 = "Test1"; + sal_Int32 tmp2 = 42; + sal_uInt32 tmp3 = 42; + OUString tmp4 = "Test2"; + OUString tmp5 = "Test3"; + ::com::sun::star::uno::Any tmp6( + ::com::sun::star::uno::makeAny( tmp1 ) + ); + ::com::sun::star::uno::Any tmp7( + ::com::sun::star::uno::makeAny( tmp2 ) + ); + ::com::sun::star::uno::Any tmp8( + ::com::sun::star::uno::makeAny( tmp3 ) + ); + ::com::sun::star::uno::Any tmp9( + ::com::sun::star::uno::makeAny( tmp4 ) + ); + ::std::optional< ::com::sun::star::uno::Any > tmp10( + ::com::sun::star::uno::makeAny( tmp5 ) + ); + ::std::optional< ::com::sun::star::uno::Any > tmp11( + ::com::sun::star::uno::makeAny( tmp1 ) + ); + + // test equality with the baseline and template specialization with + // std::optional< T > + try { + ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Any > seq1( + static_cast< sal_uInt32 >( 5 ) ); + ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Any > seq2( + static_cast< sal_uInt32 >( 5 ) ); + + // tmp11 should be ignored as it is ::std::optional< T > + ::comphelper::unwrapArgs( seq1, tmp6, tmp7, tmp8, tmp9, tmp10, tmp11 ); + unwrapArgsBaseline( seq2, tmp6, tmp7, tmp8, tmp9, tmp10 ); + ::com::sun::star::uno::Any* p1 = seq1.getArray(); + ::com::sun::star::uno::Any* p2 = seq2.getArray(); + + for( sal_Int32 i = 0; i < seq1.getLength() && i < seq2.getLength(); ++i ) { + CPPUNIT_ASSERT_EQUAL_MESSAGE( "seq1 and seq2 are equal", + p1[i], p2[i] ); + } + CPPUNIT_ASSERT_MESSAGE( "seq1 and seq2 are equal", + bool(seq1 == seq2) ); + } + catch( ::com::sun::star::lang::IllegalArgumentException& err ) { + std::stringstream ss; + ss << "IllegalArgumentException when unwrapping arguments at: " << + err.ArgumentPosition; + CPPUNIT_FAIL( ss.str() ); + } + + // test argument counting + try { + ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Any > seq( + static_cast< sal_uInt32 >( 4 ) ); + ::comphelper::unwrapArgs( seq, tmp6, tmp7, tmp10, tmp11, tmp10, tmp6 ); + } + catch( ::com::sun::star::lang::IllegalArgumentException& err ) { + CPPUNIT_ASSERT_EQUAL( static_cast< short >( 5 ), err.ArgumentPosition ); + } + + OUString test1( "Test2" ); + OUString test2( "Test2" ); + OUString test3( "Test3" ); + OUString test4( "Test4" ); + OUString test5( "Test5" ); + + try { + ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Any > seq( + static_cast< sal_uInt32 >( 4 ) ); + ::comphelper::unwrapArgs( seq, test1, test2, test3, test4, test5 ); + } + catch( ::com::sun::star::lang::IllegalArgumentException& err1 ) { + try { + ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Any > seq( + static_cast< sal_uInt32 >( 4 ) ); + unwrapArgsBaseline( seq, test1, test2, test3, test4, test5 ); + CPPUNIT_FAIL( "unwrapArgs failed while the baseline did not throw" ); + } + catch( ::com::sun::star::lang::IllegalArgumentException& err2 ) { + CPPUNIT_ASSERT_EQUAL_MESSAGE( "err1.ArgumentPosition == err2.ArgumentPosition", + err1.ArgumentPosition, err2.ArgumentPosition ); + } + } +} + +CPPUNIT_TEST_SUITE_REGISTRATION(VariadicTemplatesTest); + +CPPUNIT_PLUGIN_IMPLEMENT(); + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/comphelper/qa/weakbag/makefile.mk b/comphelper/qa/weakbag/makefile.mk new file mode 100644 index 000000000..495c68f50 --- /dev/null +++ b/comphelper/qa/weakbag/makefile.mk @@ -0,0 +1,44 @@ +# +# This file is part of the LibreOffice project. +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# This file incorporates work covered by the following license notice: +# +# 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 . +# + +PRJ := ..$/.. +PRJNAME := comphelper +TARGET := qa_weakbag + +ENABLE_EXCEPTIONS := TRUE + +.INCLUDE: settings.mk +.INCLUDE : $(PRJ)$/version.mk + +CFLAGSCXX += $(CPPUNIT_CFLAGS) + +DLLPRE = # no leading "lib" on .so files + +INCPRE += $(MISC)$/$(TARGET)$/inc + +SHL1TARGET = $(TARGET)_weakbag +SHL1OBJS = $(SLO)$/test_weakbag.obj $(SLO)$/test_weakbag_noadditional.obj +SHL1STDLIBS = $(CPPUHELPERLIB) $(CPPULIB) $(CPPUNITLIB) $(SALLIB) $(COMPHELPERLIB) +SHL1VERSIONMAP = ..$/version.map +SHL1IMPLIB = i$(SHL1TARGET) +DEF1NAME = $(SHL1TARGET) + +SLOFILES = $(SHL1OBJS) + +.INCLUDE: target.mk +.INCLUDE: _cppunit.mk diff --git a/comphelper/qa/weakbag/test_weakbag.cxx b/comphelper/qa/weakbag/test_weakbag.cxx new file mode 100644 index 000000000..d58c12501 --- /dev/null +++ b/comphelper/qa/weakbag/test_weakbag.cxx @@ -0,0 +1,60 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * 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 . + */ + +#include <com/sun/star/uno/Reference.hxx> +#include <com/sun/star/uno/XInterface.hpp> +#include <comphelper/weakbag.hxx> +#include <cppuhelper/weak.hxx> + +#include <cppunit/TestFixture.h> +#include <cppunit/extensions/HelperMacros.h> +#include <cppunit/plugin/TestPlugIn.h> + +namespace { + +class Test: public CppUnit::TestFixture { +public: + void test() { + css::uno::Reference< css::uno::XInterface > ref1(new cppu::OWeakObject); + css::uno::Reference< css::uno::XInterface > ref2(new cppu::OWeakObject); + css::uno::Reference< css::uno::XInterface > ref3(new cppu::OWeakObject); + comphelper::WeakBag< css::uno::XInterface > bag; + bag.add(ref1); + bag.add(ref1); + bag.add(ref2); + bag.add(ref2); + ref1.clear(); + bag.add(ref3); + ref3.clear(); + CPPUNIT_ASSERT_MESSAGE("remove first ref2", bag.remove() == ref2); + CPPUNIT_ASSERT_MESSAGE("remove second ref2", bag.remove() == ref2); + CPPUNIT_ASSERT_MESSAGE("remove first null", !bag.remove().is()); + CPPUNIT_ASSERT_MESSAGE("remove second null", !bag.remove().is()); + } + + CPPUNIT_TEST_SUITE(Test); + CPPUNIT_TEST(test); + CPPUNIT_TEST_SUITE_END(); +}; + +CPPUNIT_TEST_SUITE_REGISTRATION(Test); + +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/comphelper/qa/weakbag/test_weakbag_noadditional.cxx b/comphelper/qa/weakbag/test_weakbag_noadditional.cxx new file mode 100644 index 000000000..d2d66a61e --- /dev/null +++ b/comphelper/qa/weakbag/test_weakbag_noadditional.cxx @@ -0,0 +1,25 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * 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 . + */ + +#include <sal/types.h> +#include <cppunit/plugin/TestPlugIn.h> + +CPPUNIT_PLUGIN_IMPLEMENT(); + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |