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 /oox/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 'oox/qa')
37 files changed, 1406 insertions, 0 deletions
diff --git a/oox/qa/token/tokenmap-test.cxx b/oox/qa/token/tokenmap-test.cxx new file mode 100644 index 000000000..4f617189b --- /dev/null +++ b/oox/qa/token/tokenmap-test.cxx @@ -0,0 +1,54 @@ +/* -*- 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 <cppunit/TestAssert.h> +#include <cppunit/TestFixture.h> +#include <cppunit/extensions/HelperMacros.h> +#include <cppunit/plugin/TestPlugIn.h> + +#include <oox/token/tokenmap.hxx> +#include <oox/token/tokens.hxx> + +using namespace std; +using namespace com::sun::star::uno; + +namespace oox { + +class TokenmapTest: public CppUnit::TestFixture +{ +public: + void test_roundTrip(); + + CPPUNIT_TEST_SUITE(TokenmapTest); + + CPPUNIT_TEST(test_roundTrip); + CPPUNIT_TEST_SUITE_END(); + +private: + TokenMap tokenMap; +}; + +void TokenmapTest::test_roundTrip() +{ + for ( sal_Int32 nToken = 0; nToken < XML_TOKEN_COUNT; ++nToken ) + { + // check that the getIdentifier <-> getToken roundtrip works + Sequence< sal_Int8 > rUtf8Name = tokenMap.getUtf8TokenName(nToken); + sal_Int32 ret = tokenMap.getTokenFromUTF8( + reinterpret_cast< const char * >(rUtf8Name.getConstArray()), + rUtf8Name.getLength() ); + CPPUNIT_ASSERT_EQUAL(ret, nToken); + } +} + +CPPUNIT_TEST_SUITE_REGISTRATION(TokenmapTest); + +} + +CPPUNIT_PLUGIN_IMPLEMENT(); diff --git a/oox/qa/unit/CryptoTest.cxx b/oox/qa/unit/CryptoTest.cxx new file mode 100644 index 000000000..c4058619e --- /dev/null +++ b/oox/qa/unit/CryptoTest.cxx @@ -0,0 +1,426 @@ +/* -*- 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 <cppunit/plugin/TestPlugIn.h> +#include <cppunit/extensions/HelperMacros.h> +#include <cppunit/TestFixture.h> + +#include <algorithm> +#include <tools/stream.hxx> +#include <unotools/streamwrap.hxx> + +#include <oox/crypto/Standard2007Engine.hxx> +#include <oox/crypto/AgileEngine.hxx> +#include <oox/helper/binaryinputstream.hxx> +#include <oox/helper/binaryoutputstream.hxx> + +using namespace css; + +class CryptoTest : public CppUnit::TestFixture +{ +public: + void testCryptoHash(); + void testRoundUp(); + void testStandard2007(); + void testAgileEncryptionVerifier(); + void testAgileEncrpytionInfoWritingAndParsing(); + void testAgileDataIntegrityHmacKey(); + void testAgileEncryptingAndDecrypting(); + + CPPUNIT_TEST_SUITE(CryptoTest); + CPPUNIT_TEST(testCryptoHash); + CPPUNIT_TEST(testRoundUp); + CPPUNIT_TEST(testStandard2007); + CPPUNIT_TEST(testAgileEncryptionVerifier); + CPPUNIT_TEST(testAgileEncrpytionInfoWritingAndParsing); + CPPUNIT_TEST(testAgileDataIntegrityHmacKey); + CPPUNIT_TEST(testAgileEncryptingAndDecrypting); + CPPUNIT_TEST_SUITE_END(); +}; + +namespace +{ +std::string toString(std::vector<sal_uInt8> const& aInput) +{ + std::stringstream aStream; + for (auto const& aValue : aInput) + { + aStream << std::setw(2) << std::setfill('0') << std::hex << static_cast<int>(aValue); + } + + return aStream.str(); +} +} + +void CryptoTest::testCryptoHash() +{ + // Check examples from Wikipedia (https://en.wikipedia.org/wiki/HMAC) + OString aContentString("The quick brown fox jumps over the lazy dog"); + std::vector<sal_uInt8> aContent(aContentString.getStr(), + aContentString.getStr() + aContentString.getLength()); + std::vector<sal_uInt8> aKey = { 'k', 'e', 'y' }; + { + oox::crypto::CryptoHash aCryptoHash(aKey, oox::crypto::CryptoHashType::SHA1); + aCryptoHash.update(aContent); + std::vector<sal_uInt8> aHash = aCryptoHash.finalize(); + CPPUNIT_ASSERT_EQUAL(std::string("de7c9b85b8b78aa6bc8a7a36f70a90701c9db4d9"), + toString(aHash)); + } + + { + oox::crypto::CryptoHash aCryptoHash(aKey, oox::crypto::CryptoHashType::SHA256); + aCryptoHash.update(aContent); + std::vector<sal_uInt8> aHash = aCryptoHash.finalize(); + CPPUNIT_ASSERT_EQUAL( + std::string("f7bc83f430538424b13298e6aa6fb143ef4d59a14946175997479dbc2d1a3cd8"), + toString(aHash)); + } + + { + oox::crypto::CryptoHash aCryptoHash(aKey, oox::crypto::CryptoHashType::SHA512); + aCryptoHash.update(aContent); + std::vector<sal_uInt8> aHash = aCryptoHash.finalize(); + CPPUNIT_ASSERT_EQUAL( + std::string("b42af09057bac1e2d41708e48a902e09b5ff7f12ab428a4fe86653c73dd248fb82f948a549" + "f7b791a5b41915ee4d1ec3935357e4e2317250d0372afa2ebeeb3a"), + toString(aHash)); + } +} + +void CryptoTest::testRoundUp() +{ + CPPUNIT_ASSERT_EQUAL(16, oox::crypto::roundUp(16, 16)); + CPPUNIT_ASSERT_EQUAL(32, oox::crypto::roundUp(32, 16)); + CPPUNIT_ASSERT_EQUAL(64, oox::crypto::roundUp(64, 16)); + + CPPUNIT_ASSERT_EQUAL(16, oox::crypto::roundUp(01, 16)); + CPPUNIT_ASSERT_EQUAL(32, oox::crypto::roundUp(17, 16)); + CPPUNIT_ASSERT_EQUAL(32, oox::crypto::roundUp(31, 16)); +} + +void CryptoTest::testStandard2007() +{ + oox::crypto::Standard2007Engine aEngine; + { + aEngine.setupEncryption("Password"); + + SvMemoryStream aEncryptionInfo; + oox::BinaryXOutputStream aBinaryEncryptionInfoOutputStream( + new utl::OSeekableOutputStreamWrapper(aEncryptionInfo), false); + + aEngine.writeEncryptionInfo(aBinaryEncryptionInfoOutputStream); + aBinaryEncryptionInfoOutputStream.close(); + + CPPUNIT_ASSERT_EQUAL(sal_uInt64(224), aEncryptionInfo.GetSize()); + } + + SvMemoryStream aUnencryptedInput; + SvMemoryStream aEncryptedStream; + + OString aTestString = OUStringToOString("1234567890ABCDEFG", RTL_TEXTENCODING_UTF8); + + aUnencryptedInput.WriteBytes(aTestString.getStr(), aTestString.getLength() + 1); + aUnencryptedInput.Seek(STREAM_SEEK_TO_BEGIN); + + { + uno::Reference<io::XInputStream> xInputStream( + new utl::OSeekableInputStreamWrapper(aUnencryptedInput)); + uno::Reference<io::XOutputStream> xOutputStream( + new utl::OSeekableOutputStreamWrapper(aEncryptedStream)); + + aEngine.encrypt(xInputStream, xOutputStream, aUnencryptedInput.GetSize()); + + xOutputStream->flush(); + + const sal_uInt8* pData = static_cast<const sal_uInt8*>(aEncryptedStream.GetData()); + sal_uInt64 nSize = aEncryptedStream.GetSize(); + + std::vector<sal_uInt8> aData(nSize); + std::copy(pData, pData + nSize, aData.data()); + + CPPUNIT_ASSERT_EQUAL(sal_uInt64(40), nSize); + } + + aEncryptedStream.Seek(STREAM_SEEK_TO_BEGIN); + SvMemoryStream aUnencryptedOutput; + + { + oox::BinaryXInputStream aBinaryInputStream( + new utl::OSeekableInputStreamWrapper(aEncryptedStream), true); + oox::BinaryXOutputStream aBinaryOutputStream( + new utl::OSeekableOutputStreamWrapper(aUnencryptedOutput), true); + + aEngine.decrypt(aBinaryInputStream, aBinaryOutputStream); + aBinaryOutputStream.close(); + aBinaryInputStream.close(); + + const char* pData = static_cast<const char*>(aUnencryptedOutput.GetData()); + sal_uInt64 nSize = aUnencryptedOutput.GetSize(); + + CPPUNIT_ASSERT_EQUAL(sal_uInt64(18), nSize); + + OString aString(pData); + + CPPUNIT_ASSERT_EQUAL(aTestString, aString); + } +} + +void CryptoTest::testAgileEncryptionVerifier() +{ + oox::crypto::AgileEngine aEngine; + + OUString aPassword("Password"); + + aEngine.setupEncryptionParameters({ 100000, 16, 128, 20, 16, OUString("AES"), + OUString("ChainingModeCBC"), OUString("SHA1") }); + + CPPUNIT_ASSERT_EQUAL(true, aEngine.generateAndEncryptVerifierHash(aPassword)); + CPPUNIT_ASSERT_EQUAL(false, aEngine.decryptAndCheckVerifierHash("Wrong")); + CPPUNIT_ASSERT_EQUAL(true, aEngine.decryptAndCheckVerifierHash(aPassword)); + + aEngine.setupEncryptionParameters({ 100000, 16, 256, 64, 16, OUString("AES"), + OUString("ChainingModeCBC"), OUString("SHA512") }); + + CPPUNIT_ASSERT_EQUAL(true, aEngine.generateAndEncryptVerifierHash(aPassword)); + CPPUNIT_ASSERT_EQUAL(false, aEngine.decryptAndCheckVerifierHash("Wrong")); + CPPUNIT_ASSERT_EQUAL(true, aEngine.decryptAndCheckVerifierHash(aPassword)); +} + +void CryptoTest::testAgileEncrpytionInfoWritingAndParsing() +{ + OUString aPassword("Password"); + std::vector<sal_uInt8> aKeyDataSalt; + + { // Preset AES128 - SHA1 + SvMemoryStream aEncryptionInfo; + { + oox::crypto::AgileEngine aEngine; + + aEngine.setPreset(oox::crypto::AgileEncryptionPreset::AES_128_SHA1); + aEngine.setupEncryption(aPassword); + aKeyDataSalt = aEngine.getInfo().keyDataSalt; + + oox::BinaryXOutputStream aBinaryEncryptionInfoOutputStream( + new utl::OSeekableOutputStreamWrapper(aEncryptionInfo), true); + + aEngine.writeEncryptionInfo(aBinaryEncryptionInfoOutputStream); + aBinaryEncryptionInfoOutputStream.close(); + + CPPUNIT_ASSERT_EQUAL(sal_uInt64(996), aEncryptionInfo.GetSize()); + } + + aEncryptionInfo.Seek(STREAM_SEEK_TO_BEGIN); + + { + oox::crypto::AgileEngine aEngine; + + uno::Reference<io::XInputStream> xInputStream( + new utl::OSeekableInputStreamWrapper(aEncryptionInfo)); + + xInputStream->skipBytes(4); // Encryption type -> Agile + + CPPUNIT_ASSERT(aEngine.readEncryptionInfo(xInputStream)); + + oox::crypto::AgileEncryptionInfo& rInfo = aEngine.getInfo(); + CPPUNIT_ASSERT_EQUAL(sal_Int32(100000), rInfo.spinCount); + CPPUNIT_ASSERT_EQUAL(sal_Int32(16), rInfo.saltSize); + CPPUNIT_ASSERT_EQUAL(sal_Int32(128), rInfo.keyBits); + CPPUNIT_ASSERT_EQUAL(sal_Int32(20), rInfo.hashSize); + CPPUNIT_ASSERT_EQUAL(sal_Int32(16), rInfo.blockSize); + CPPUNIT_ASSERT_EQUAL(OUString("AES"), rInfo.cipherAlgorithm); + CPPUNIT_ASSERT_EQUAL(OUString("ChainingModeCBC"), rInfo.cipherChaining); + CPPUNIT_ASSERT_EQUAL(OUString("SHA1"), rInfo.hashAlgorithm); + CPPUNIT_ASSERT_EQUAL(toString(aKeyDataSalt), toString(rInfo.keyDataSalt)); + + CPPUNIT_ASSERT_EQUAL(false, aEngine.decryptAndCheckVerifierHash("Wrong")); + CPPUNIT_ASSERT_EQUAL(true, aEngine.decryptAndCheckVerifierHash(aPassword)); + } + } + + { // Preset AES256 - SHA512 + SvMemoryStream aEncryptionInfo; + { + oox::crypto::AgileEngine aEngine; + + aEngine.setPreset(oox::crypto::AgileEncryptionPreset::AES_256_SHA512); + aEngine.setupEncryption(aPassword); + aKeyDataSalt = aEngine.getInfo().keyDataSalt; + + oox::BinaryXOutputStream aBinaryEncryptionInfoOutputStream( + new utl::OSeekableOutputStreamWrapper(aEncryptionInfo), true); + + aEngine.writeEncryptionInfo(aBinaryEncryptionInfoOutputStream); + aBinaryEncryptionInfoOutputStream.close(); + + CPPUNIT_ASSERT_EQUAL(sal_uInt64(1112), aEncryptionInfo.GetSize()); + } + + aEncryptionInfo.Seek(STREAM_SEEK_TO_BEGIN); + + { + oox::crypto::AgileEngine aEngine; + + uno::Reference<io::XInputStream> xInputStream( + new utl::OSeekableInputStreamWrapper(aEncryptionInfo)); + + xInputStream->skipBytes(4); // Encryption type -> Agile + + CPPUNIT_ASSERT(aEngine.readEncryptionInfo(xInputStream)); + + oox::crypto::AgileEncryptionInfo& rInfo = aEngine.getInfo(); + CPPUNIT_ASSERT_EQUAL(sal_Int32(100000), rInfo.spinCount); + CPPUNIT_ASSERT_EQUAL(sal_Int32(16), rInfo.saltSize); + CPPUNIT_ASSERT_EQUAL(sal_Int32(256), rInfo.keyBits); + CPPUNIT_ASSERT_EQUAL(sal_Int32(64), rInfo.hashSize); + CPPUNIT_ASSERT_EQUAL(sal_Int32(16), rInfo.blockSize); + CPPUNIT_ASSERT_EQUAL(OUString("AES"), rInfo.cipherAlgorithm); + CPPUNIT_ASSERT_EQUAL(OUString("ChainingModeCBC"), rInfo.cipherChaining); + CPPUNIT_ASSERT_EQUAL(OUString("SHA512"), rInfo.hashAlgorithm); + CPPUNIT_ASSERT_EQUAL(toString(aKeyDataSalt), toString(rInfo.keyDataSalt)); + + CPPUNIT_ASSERT_EQUAL(false, aEngine.decryptAndCheckVerifierHash("Wrong")); + CPPUNIT_ASSERT_EQUAL(true, aEngine.decryptAndCheckVerifierHash(aPassword)); + } + } +} + +void CryptoTest::testAgileDataIntegrityHmacKey() +{ + OUString aPassword("Password"); + + std::vector<sal_uInt8> aKeyDataSalt; + + std::vector<sal_uInt8> aHmacKey; + std::vector<sal_uInt8> aHmacEncryptedKey; + + SvMemoryStream aEncryptionInfo; + { + oox::crypto::AgileEngine aEngine; + aEngine.setupEncryption(aPassword); + oox::BinaryXOutputStream aBinaryEncryptionInfoOutputStream( + new utl::OSeekableOutputStreamWrapper(aEncryptionInfo), true); + aEngine.writeEncryptionInfo(aBinaryEncryptionInfoOutputStream); + aBinaryEncryptionInfoOutputStream.close(); + + aHmacKey = aEngine.getInfo().hmacKey; + aKeyDataSalt = aEngine.getInfo().keyDataSalt; + aHmacEncryptedKey = aEngine.getInfo().hmacEncryptedKey; + } + + aEncryptionInfo.Seek(STREAM_SEEK_TO_BEGIN); + + { + oox::crypto::AgileEngine aEngine; + + uno::Reference<io::XInputStream> xInputStream( + new utl::OSeekableInputStreamWrapper(aEncryptionInfo)); + + xInputStream->skipBytes(4); // Encryption type -> Agile + + CPPUNIT_ASSERT(aEngine.readEncryptionInfo(xInputStream)); + CPPUNIT_ASSERT(aEngine.generateEncryptionKey(aPassword)); + + CPPUNIT_ASSERT_EQUAL(toString(aKeyDataSalt), toString(aEngine.getInfo().keyDataSalt)); + + CPPUNIT_ASSERT_EQUAL(toString(aHmacEncryptedKey), + toString(aEngine.getInfo().hmacEncryptedKey)); + + CPPUNIT_ASSERT_EQUAL(size_t(64), aHmacKey.size()); + CPPUNIT_ASSERT_EQUAL(toString(aHmacKey), toString(aEngine.getInfo().hmacKey)); + } +} + +void CryptoTest::testAgileEncryptingAndDecrypting() +{ + OUString aPassword("Password"); + + SvMemoryStream aEncryptionInfo; + SvMemoryStream aEncryptedStream; + + OString aTestString = OUStringToOString("1234567890ABCDEFGH", RTL_TEXTENCODING_UTF8); + + { + oox::crypto::AgileEngine aEngine; + + // Setup input + SvMemoryStream aUnencryptedInput; + uno::Reference<io::XInputStream> xInputStream( + new utl::OSeekableInputStreamWrapper(aUnencryptedInput)); + + aUnencryptedInput.WriteBytes(aTestString.getStr(), aTestString.getLength() + 1); + aUnencryptedInput.Seek(STREAM_SEEK_TO_BEGIN); + + // Setup output + uno::Reference<io::XOutputStream> xOutputStream( + new utl::OSeekableOutputStreamWrapper(aEncryptedStream)); + + // Write content + aEngine.setupEncryption(aPassword); + aEngine.encrypt(xInputStream, xOutputStream, aUnencryptedInput.GetSize()); + xOutputStream->flush(); + + // Check content + sal_uInt64 nSize = aEncryptedStream.GetSize(); + + CPPUNIT_ASSERT_EQUAL(sal_uInt64(40), nSize); + + // Setup and write encryption info + oox::BinaryXOutputStream aBinaryEncryptionInfoOutputStream( + new utl::OSeekableOutputStreamWrapper(aEncryptionInfo), true); + aEngine.writeEncryptionInfo(aBinaryEncryptionInfoOutputStream); + aBinaryEncryptionInfoOutputStream.close(); + } + + aEncryptedStream.Seek(STREAM_SEEK_TO_BEGIN); + aEncryptionInfo.Seek(STREAM_SEEK_TO_BEGIN); + + { + oox::crypto::AgileEngine aEngine; + + // Read encryption info + uno::Reference<io::XInputStream> xEncryptionInfo( + new utl::OSeekableInputStreamWrapper(aEncryptionInfo)); + + xEncryptionInfo->skipBytes(4); // Encryption type -> Agile + + CPPUNIT_ASSERT(aEngine.readEncryptionInfo(xEncryptionInfo)); + + // Setup password + CPPUNIT_ASSERT(aEngine.generateEncryptionKey(aPassword)); + + // Setup encrypted input stream + oox::BinaryXInputStream aBinaryInputStream( + new utl::OSeekableInputStreamWrapper(aEncryptedStream), true); + + // Setup output stream + SvMemoryStream aUnencryptedOutput; + oox::BinaryXOutputStream aBinaryOutputStream( + new utl::OSeekableOutputStreamWrapper(aUnencryptedOutput), true); + + // Decrypt + aEngine.decrypt(aBinaryInputStream, aBinaryOutputStream); + aBinaryOutputStream.close(); + aBinaryInputStream.close(); + + // Check decrypted output + CPPUNIT_ASSERT_EQUAL(sal_uInt64(19), aUnencryptedOutput.GetSize()); + + OString aString(static_cast<const char*>(aUnencryptedOutput.GetData())); + CPPUNIT_ASSERT_EQUAL(aTestString, aString); + + // Check data integrity + CPPUNIT_ASSERT_EQUAL(true, aEngine.checkDataIntegrity()); + } +} + +CPPUNIT_TEST_SUITE_REGISTRATION(CryptoTest); + +CPPUNIT_PLUGIN_IMPLEMENT(); + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/oox/qa/unit/data/chart-data-label-char-color.docx b/oox/qa/unit/data/chart-data-label-char-color.docx Binary files differnew file mode 100644 index 000000000..0e389f923 --- /dev/null +++ b/oox/qa/unit/data/chart-data-label-char-color.docx diff --git a/oox/qa/unit/data/customshape-position.docx b/oox/qa/unit/data/customshape-position.docx Binary files differnew file mode 100644 index 000000000..227928f20 --- /dev/null +++ b/oox/qa/unit/data/customshape-position.docx diff --git a/oox/qa/unit/data/gradient-multistep-transparency.pptx b/oox/qa/unit/data/gradient-multistep-transparency.pptx Binary files differnew file mode 100644 index 000000000..83946c71b --- /dev/null +++ b/oox/qa/unit/data/gradient-multistep-transparency.pptx diff --git a/oox/qa/unit/data/graphic-stroke.pptx b/oox/qa/unit/data/graphic-stroke.pptx Binary files differnew file mode 100644 index 000000000..f4465476f --- /dev/null +++ b/oox/qa/unit/data/graphic-stroke.pptx diff --git a/oox/qa/unit/data/group-spt202.docx b/oox/qa/unit/data/group-spt202.docx Binary files differnew file mode 100644 index 000000000..14bf00b50 --- /dev/null +++ b/oox/qa/unit/data/group-spt202.docx diff --git a/oox/qa/unit/data/import-characters.pptx b/oox/qa/unit/data/import-characters.pptx Binary files differnew file mode 100644 index 000000000..293380236 --- /dev/null +++ b/oox/qa/unit/data/import-characters.pptx diff --git a/oox/qa/unit/data/import-mce.pptx b/oox/qa/unit/data/import-mce.pptx Binary files differnew file mode 100644 index 000000000..65cf1cbab --- /dev/null +++ b/oox/qa/unit/data/import-mce.pptx diff --git a/oox/qa/unit/data/layout-flow-alt-alone.docx b/oox/qa/unit/data/layout-flow-alt-alone.docx Binary files differnew file mode 100644 index 000000000..59c2db23d --- /dev/null +++ b/oox/qa/unit/data/layout-flow-alt-alone.docx diff --git a/oox/qa/unit/data/multiple-group-shapes.docx b/oox/qa/unit/data/multiple-group-shapes.docx Binary files differnew file mode 100644 index 000000000..c751bcdf6 --- /dev/null +++ b/oox/qa/unit/data/multiple-group-shapes.docx diff --git a/oox/qa/unit/data/preset-adjust-value.pptx b/oox/qa/unit/data/preset-adjust-value.pptx Binary files differnew file mode 100644 index 000000000..d1d570a19 --- /dev/null +++ b/oox/qa/unit/data/preset-adjust-value.pptx diff --git a/oox/qa/unit/data/shape-non-autosize-with-text.docx b/oox/qa/unit/data/shape-non-autosize-with-text.docx Binary files differnew file mode 100644 index 000000000..b9ae501f4 --- /dev/null +++ b/oox/qa/unit/data/shape-non-autosize-with-text.docx diff --git a/oox/qa/unit/data/shape-text-adjust-left.pptx b/oox/qa/unit/data/shape-text-adjust-left.pptx Binary files differnew file mode 100644 index 000000000..d197425b9 --- /dev/null +++ b/oox/qa/unit/data/shape-text-adjust-left.pptx diff --git a/oox/qa/unit/data/shape-text-alignment.pptx b/oox/qa/unit/data/shape-text-alignment.pptx Binary files differnew file mode 100644 index 000000000..ff4ff06f2 --- /dev/null +++ b/oox/qa/unit/data/shape-text-alignment.pptx diff --git a/oox/qa/unit/data/tdf131082.pptx b/oox/qa/unit/data/tdf131082.pptx Binary files differnew file mode 100644 index 000000000..dbe88126f --- /dev/null +++ b/oox/qa/unit/data/tdf131082.pptx diff --git a/oox/qa/unit/data/transparent-text.pptx b/oox/qa/unit/data/transparent-text.pptx Binary files differnew file mode 100644 index 000000000..b7b3ede4d --- /dev/null +++ b/oox/qa/unit/data/transparent-text.pptx diff --git a/oox/qa/unit/data/vba/complex1.bin b/oox/qa/unit/data/vba/complex1.bin Binary files differnew file mode 100644 index 000000000..390208290 --- /dev/null +++ b/oox/qa/unit/data/vba/complex1.bin diff --git a/oox/qa/unit/data/vba/reference/complex1.bin b/oox/qa/unit/data/vba/reference/complex1.bin Binary files differnew file mode 100644 index 000000000..335b8e808 --- /dev/null +++ b/oox/qa/unit/data/vba/reference/complex1.bin diff --git a/oox/qa/unit/data/vba/reference/simple1.bin b/oox/qa/unit/data/vba/reference/simple1.bin Binary files differnew file mode 100644 index 000000000..a4644fbb7 --- /dev/null +++ b/oox/qa/unit/data/vba/reference/simple1.bin diff --git a/oox/qa/unit/data/vba/reference/simple2.bin b/oox/qa/unit/data/vba/reference/simple2.bin Binary files differnew file mode 100644 index 000000000..5de3f5ae0 --- /dev/null +++ b/oox/qa/unit/data/vba/reference/simple2.bin diff --git a/oox/qa/unit/data/vba/reference/simple3.bin b/oox/qa/unit/data/vba/reference/simple3.bin new file mode 100644 index 000000000..a38e8a868 --- /dev/null +++ b/oox/qa/unit/data/vba/reference/simple3.bin @@ -0,0 +1 @@ +° diff --git a/oox/qa/unit/data/vba/reference/spec321.bin b/oox/qa/unit/data/vba/reference/spec321.bin Binary files differnew file mode 100644 index 000000000..3120c7f50 --- /dev/null +++ b/oox/qa/unit/data/vba/reference/spec321.bin diff --git a/oox/qa/unit/data/vba/reference/spec322.bin b/oox/qa/unit/data/vba/reference/spec322.bin Binary files differnew file mode 100644 index 000000000..7724b62a4 --- /dev/null +++ b/oox/qa/unit/data/vba/reference/spec322.bin diff --git a/oox/qa/unit/data/vba/reference/spec323.bin b/oox/qa/unit/data/vba/reference/spec323.bin Binary files differnew file mode 100644 index 000000000..51104ee0b --- /dev/null +++ b/oox/qa/unit/data/vba/reference/spec323.bin diff --git a/oox/qa/unit/data/vba/simple1.bin b/oox/qa/unit/data/vba/simple1.bin Binary files differnew file mode 100644 index 000000000..d59c1d5ef --- /dev/null +++ b/oox/qa/unit/data/vba/simple1.bin diff --git a/oox/qa/unit/data/vba/simple2.bin b/oox/qa/unit/data/vba/simple2.bin Binary files differnew file mode 100644 index 000000000..1b9b88b16 --- /dev/null +++ b/oox/qa/unit/data/vba/simple2.bin diff --git a/oox/qa/unit/data/vba/simple3.bin b/oox/qa/unit/data/vba/simple3.bin new file mode 100644 index 000000000..72060e8a2 --- /dev/null +++ b/oox/qa/unit/data/vba/simple3.bin @@ -0,0 +1 @@ + diff --git a/oox/qa/unit/data/vba/spec321.bin b/oox/qa/unit/data/vba/spec321.bin new file mode 100644 index 000000000..c5d48c9fc --- /dev/null +++ b/oox/qa/unit/data/vba/spec321.bin @@ -0,0 +1 @@ +abcdefghijklmnopqrstuv.
\ No newline at end of file diff --git a/oox/qa/unit/data/vba/spec322.bin b/oox/qa/unit/data/vba/spec322.bin new file mode 100644 index 000000000..781c426c0 --- /dev/null +++ b/oox/qa/unit/data/vba/spec322.bin @@ -0,0 +1 @@ +#aaabcdefaaaaghijaaaaaklaaamnopqaaaaaaaaaaaarstuvwxyzaaa
\ No newline at end of file diff --git a/oox/qa/unit/data/vba/spec323.bin b/oox/qa/unit/data/vba/spec323.bin new file mode 100644 index 000000000..9ca58b98a --- /dev/null +++ b/oox/qa/unit/data/vba/spec323.bin @@ -0,0 +1 @@ +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
\ No newline at end of file diff --git a/oox/qa/unit/drawingml.cxx b/oox/qa/unit/drawingml.cxx new file mode 100644 index 000000000..7fcee1756 --- /dev/null +++ b/oox/qa/unit/drawingml.cxx @@ -0,0 +1,270 @@ +/* -*- 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 <test/bootstrapfixture.hxx> +#include <unotest/macros_test.hxx> + +#include <com/sun/star/awt/Gradient.hpp> +#include <com/sun/star/beans/XPropertySet.hpp> +#include <com/sun/star/container/XNamed.hpp> +#include <com/sun/star/drawing/XDrawPagesSupplier.hpp> +#include <com/sun/star/drawing/FillStyle.hpp> +#include <com/sun/star/drawing/XShape.hpp> +#include <com/sun/star/frame/Desktop.hpp> +#include <com/sun/star/frame/XStorable.hpp> +#include <com/sun/star/drawing/EnhancedCustomShapeAdjustmentValue.hpp> +#include <com/sun/star/chart2/XChartDocument.hpp> +#include <com/sun/star/chart2/XCoordinateSystemContainer.hpp> +#include <com/sun/star/chart2/XChartTypeContainer.hpp> +#include <com/sun/star/chart2/XDataSeriesContainer.hpp> +#include <com/sun/star/chart2/XDataPointCustomLabelField.hpp> +#include <com/sun/star/style/ParagraphAdjust.hpp> +#include <com/sun/star/drawing/TextHorizontalAdjust.hpp> + +#include <unotools/mediadescriptor.hxx> +#include <unotools/tempfile.hxx> + +using namespace ::com::sun::star; + +namespace +{ +/// Gets one child of xShape, which one is specified by nIndex. +uno::Reference<drawing::XShape> getChildShape(const uno::Reference<drawing::XShape>& xShape, + sal_Int32 nIndex) +{ + uno::Reference<container::XIndexAccess> xGroup(xShape, uno::UNO_QUERY); + CPPUNIT_ASSERT(xGroup.is()); + + CPPUNIT_ASSERT(xGroup->getCount() > nIndex); + + uno::Reference<drawing::XShape> xRet(xGroup->getByIndex(nIndex), uno::UNO_QUERY); + CPPUNIT_ASSERT(xRet.is()); + + return xRet; +} +} + +/// oox drawingml tests. +class OoxDrawingmlTest : public test::BootstrapFixture, public unotest::MacrosTest +{ +private: + uno::Reference<lang::XComponent> mxComponent; + +public: + void setUp() override; + void tearDown() override; + uno::Reference<lang::XComponent>& getComponent() { return mxComponent; } + void load(const OUString& rURL); + void loadAndReload(const OUString& rURL, const OUString& rFilterName); +}; + +void OoxDrawingmlTest::setUp() +{ + test::BootstrapFixture::setUp(); + + mxDesktop.set(frame::Desktop::create(mxComponentContext)); +} + +void OoxDrawingmlTest::tearDown() +{ + if (mxComponent.is()) + mxComponent->dispose(); + + test::BootstrapFixture::tearDown(); +} + +void OoxDrawingmlTest::load(const OUString& rURL) { mxComponent = loadFromDesktop(rURL); } + +void OoxDrawingmlTest::loadAndReload(const OUString& rURL, const OUString& rFilterName) +{ + load(rURL); + uno::Reference<frame::XStorable> xStorable(mxComponent, uno::UNO_QUERY); + utl::MediaDescriptor aMediaDescriptor; + aMediaDescriptor["FilterName"] <<= rFilterName; + utl::TempFile aTempFile; + xStorable->storeToURL(aTempFile.GetURL(), aMediaDescriptor.getAsConstPropertyValueList()); + mxComponent->dispose(); + validate(aTempFile.GetFileName(), test::OOXML); + mxComponent = loadFromDesktop(aTempFile.GetURL()); +} + +char const DATA_DIRECTORY[] = "/oox/qa/unit/data/"; + +CPPUNIT_TEST_FIXTURE(OoxDrawingmlTest, testTransparentText) +{ + OUString aURL = m_directories.getURLFromSrc(DATA_DIRECTORY) + "transparent-text.pptx"; + loadAndReload(aURL, "Impress Office Open XML"); + + uno::Reference<drawing::XDrawPagesSupplier> xDrawPagesSupplier(getComponent(), uno::UNO_QUERY); + uno::Reference<drawing::XDrawPage> xDrawPage(xDrawPagesSupplier->getDrawPages()->getByIndex(0), + uno::UNO_QUERY); + uno::Reference<container::XEnumerationAccess> xShape(xDrawPage->getByIndex(0), uno::UNO_QUERY); + uno::Reference<container::XEnumerationAccess> xParagraph( + xShape->createEnumeration()->nextElement(), uno::UNO_QUERY); + uno::Reference<beans::XPropertySet> xPortion(xParagraph->createEnumeration()->nextElement(), + uno::UNO_QUERY); + + sal_Int16 nTransparency = 0; + xPortion->getPropertyValue("CharTransparence") >>= nTransparency; + + // Without the accompanying fix in place, this test would have failed with: + // - Expected: 75 + // - Actual : 0 + // i.e. the transparency of the character color was lost on import/export. + CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int16>(75), nTransparency); +} + +CPPUNIT_TEST_FIXTURE(OoxDrawingmlTest, testTdf131082) +{ + OUString aURL = m_directories.getURLFromSrc(DATA_DIRECTORY) + "tdf131082.pptx"; + loadAndReload(aURL, "Impress Office Open XML"); + + uno::Reference<drawing::XDrawPagesSupplier> xDrawPagesSupplier(getComponent(), uno::UNO_QUERY); + uno::Reference<drawing::XDrawPage> xDrawPage(xDrawPagesSupplier->getDrawPages()->getByIndex(0), + uno::UNO_QUERY); + + uno::Reference<drawing::XShape> xShape(xDrawPage->getByIndex(0), uno::UNO_QUERY); + uno::Reference<beans::XPropertySet> XPropSet(getChildShape(getChildShape(xShape, 0), 0), + uno::UNO_QUERY); + + drawing::FillStyle eFillStyle = drawing::FillStyle_NONE; + XPropSet->getPropertyValue("FillStyle") >>= eFillStyle; + + // Without the accompanying fix in place, this test would have failed with: + // with drawing::FillStyle_NONE - 0 + CPPUNIT_ASSERT_EQUAL(drawing::FillStyle_SOLID, eFillStyle); +} + +CPPUNIT_TEST_FIXTURE(OoxDrawingmlTest, testPresetAdjustValue) +{ + OUString aURL = m_directories.getURLFromSrc(DATA_DIRECTORY) + "preset-adjust-value.pptx"; + + load(aURL); + + uno::Reference<drawing::XDrawPagesSupplier> xDrawPagesSupplier(getComponent(), uno::UNO_QUERY); + uno::Reference<drawing::XDrawPage> xDrawPage(xDrawPagesSupplier->getDrawPages()->getByIndex(0), + uno::UNO_QUERY); + uno::Reference<drawing::XShape> xShape(xDrawPage->getByIndex(0), uno::UNO_QUERY); + uno::Reference<beans::XPropertySet> xShapeProps(xShape, uno::UNO_QUERY); + uno::Sequence<beans::PropertyValue> aGeoPropSeq; + xShapeProps->getPropertyValue("CustomShapeGeometry") >>= aGeoPropSeq; + comphelper::SequenceAsHashMap aGeoPropMap(aGeoPropSeq); + uno::Sequence<drawing::EnhancedCustomShapeAdjustmentValue> aAdjustmentSeq; + aGeoPropMap.getValue("AdjustmentValues") >>= aAdjustmentSeq; + CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32>(1), aAdjustmentSeq.getLength()); + // Without the accompanying fix in place, this test would have failed with: + // - Expected: 11587 + // - Actual : 10813 + // i.e. the adjust value was set from the placeholder, not from the shape. + CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32>(11587), aAdjustmentSeq[0].Value.get<sal_Int32>()); +} + +CPPUNIT_TEST_FIXTURE(OoxDrawingmlTest, testChartDataLabelCharColor) +{ + OUString aURL + = m_directories.getURLFromSrc(DATA_DIRECTORY) + "chart-data-label-char-color.docx"; + load(aURL); + + uno::Reference<drawing::XDrawPagesSupplier> xDrawPagesSupplier(getComponent(), uno::UNO_QUERY); + uno::Reference<drawing::XDrawPage> xDrawPage(xDrawPagesSupplier->getDrawPages()->getByIndex(0), + uno::UNO_QUERY); + uno::Reference<beans::XPropertySet> xShape(xDrawPage->getByIndex(0), uno::UNO_QUERY); + uno::Reference<chart2::XChartDocument> xModel(xShape->getPropertyValue("Model"), + uno::UNO_QUERY); + uno::Reference<chart2::XCoordinateSystemContainer> xDiagram(xModel->getFirstDiagram(), + uno::UNO_QUERY); + + uno::Reference<chart2::XChartTypeContainer> xCoordinateSystem( + xDiagram->getCoordinateSystems()[0], uno::UNO_QUERY); + + uno::Reference<chart2::XDataSeriesContainer> xChartType(xCoordinateSystem->getChartTypes()[0], + uno::UNO_QUERY); + + uno::Reference<chart2::XDataSeries> xDataSeries = xChartType->getDataSeries()[0]; + + uno::Reference<beans::XPropertySet> xDataPoint = xDataSeries->getDataPointByIndex(0); + + uno::Sequence<uno::Reference<chart2::XDataPointCustomLabelField>> aLabels; + xDataPoint->getPropertyValue("CustomLabelFields") >>= aLabels; + uno::Reference<beans::XPropertySet> xLabel = aLabels[0]; + + sal_Int32 nCharColor = 0; + xLabel->getPropertyValue("CharColor") >>= nCharColor; + // Without the accompanying fix in place, this test would have failed with: + // - Expected: 16777215 + // - Actual : -1 + // i.e. the data label had no explicit (white) color. + CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32>(0xffffff), nCharColor); +} + +CPPUNIT_TEST_FIXTURE(OoxDrawingmlTest, testGradientMultiStepTransparency) +{ + // Load a document with a multi-step gradient. + OUString aURL + = m_directories.getURLFromSrc(DATA_DIRECTORY) + "gradient-multistep-transparency.pptx"; + load(aURL); + + // Check the end transparency of the gradient. + uno::Reference<drawing::XDrawPagesSupplier> xDrawPagesSupplier(getComponent(), uno::UNO_QUERY); + uno::Reference<drawing::XDrawPage> xDrawPage(xDrawPagesSupplier->getDrawPages()->getByIndex(0), + uno::UNO_QUERY); + uno::Reference<container::XNamed> xShape(xDrawPage->getByIndex(1), uno::UNO_QUERY); + CPPUNIT_ASSERT_EQUAL(OUString("Rectangle 4"), xShape->getName()); + uno::Reference<beans::XPropertySet> xShapeProps(xShape, uno::UNO_QUERY); + awt::Gradient aTransparence; + xShapeProps->getPropertyValue("FillTransparenceGradient") >>= aTransparence; + + // Without the accompanying fix in place, this test would have failed with: + // - Expected: 16777215 (0xffffff) + // - Actual : 3487029 (0x353535) + // i.e. the end transparency was not 100%, but was 21%, leading to an unexpected visible line on + // the right of this shape. + CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32>(0xffffff), aTransparence.EndColor); +} + +CPPUNIT_TEST_FIXTURE(OoxDrawingmlTest, testShapeTextAlignment) +{ + OUString aURL = m_directories.getURLFromSrc(DATA_DIRECTORY) + "shape-text-alignment.pptx"; + load(aURL); + + uno::Reference<drawing::XDrawPagesSupplier> xDrawPagesSupplier(getComponent(), uno::UNO_QUERY); + uno::Reference<drawing::XDrawPage> xDrawPage(xDrawPagesSupplier->getDrawPages()->getByIndex(0), + uno::UNO_QUERY); + uno::Reference<beans::XPropertySet> xShape(xDrawPage->getByIndex(0), uno::UNO_QUERY); + sal_Int16 nParaAdjust = -1; + CPPUNIT_ASSERT(xShape->getPropertyValue("ParaAdjust") >>= nParaAdjust); + // Without the accompanying fix in place, this test would have failed with: + // - Expected: 0 + // - Actual : 3 + // i.e. text which is meant to be left-aligned was centered at a paragraph level. + CPPUNIT_ASSERT_EQUAL(style::ParagraphAdjust_LEFT, + static_cast<style::ParagraphAdjust>(nParaAdjust)); +} + +CPPUNIT_TEST_FIXTURE(OoxDrawingmlTest, testShapeTextAdjustLeft) +{ + OUString aURL = m_directories.getURLFromSrc(DATA_DIRECTORY) + "shape-text-adjust-left.pptx"; + load(aURL); + + uno::Reference<drawing::XDrawPagesSupplier> xDrawPagesSupplier(getComponent(), uno::UNO_QUERY); + uno::Reference<drawing::XDrawPage> xDrawPage(xDrawPagesSupplier->getDrawPages()->getByIndex(0), + uno::UNO_QUERY); + uno::Reference<beans::XPropertySet> xShape(xDrawPage->getByIndex(0), uno::UNO_QUERY); + drawing::TextHorizontalAdjust eAdjust; + // Without the accompanying fix in place, this test would have failed with: + // - Expected: 3 (center) + // - Actual : 1 (block) + // i.e. text was center-adjusted, not default-adjusted (~left). + CPPUNIT_ASSERT(xShape->getPropertyValue("TextHorizontalAdjust") >>= eAdjust); + CPPUNIT_ASSERT_EQUAL(drawing::TextHorizontalAdjust_BLOCK, eAdjust); +} + +CPPUNIT_PLUGIN_IMPLEMENT(); + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/oox/qa/unit/mathml.cxx b/oox/qa/unit/mathml.cxx new file mode 100644 index 000000000..bb629ccc9 --- /dev/null +++ b/oox/qa/unit/mathml.cxx @@ -0,0 +1,72 @@ +/* -*- 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 <test/bootstrapfixture.hxx> +#include <unotest/macros_test.hxx> + +#include <com/sun/star/drawing/XDrawPagesSupplier.hpp> +#include <com/sun/star/frame/Desktop.hpp> + +using namespace ::com::sun::star; + +/// oox mathml tests. +class OoxMathmlTest : public test::BootstrapFixture, public unotest::MacrosTest +{ +private: + uno::Reference<lang::XComponent> mxComponent; + +public: + void setUp() override; + void tearDown() override; + uno::Reference<lang::XComponent>& getComponent() { return mxComponent; } +}; + +void OoxMathmlTest::setUp() +{ + test::BootstrapFixture::setUp(); + + mxDesktop.set(frame::Desktop::create(mxComponentContext)); +} + +void OoxMathmlTest::tearDown() +{ + if (mxComponent.is()) + mxComponent->dispose(); + + test::BootstrapFixture::tearDown(); +} + +char const DATA_DIRECTORY[] = "/oox/qa/unit/data/"; + +CPPUNIT_TEST_FIXTURE(OoxMathmlTest, testImportCharacters) +{ + OUString aURL = m_directories.getURLFromSrc(DATA_DIRECTORY) + "import-characters.pptx"; + // Without the accompanying fix in place, this failed with an assertion failure on import. + getComponent() = loadFromDesktop(aURL); + CPPUNIT_ASSERT(getComponent().is()); +} + +CPPUNIT_TEST_FIXTURE(OoxMathmlTest, testImportMce) +{ + OUString aURL = m_directories.getURLFromSrc(DATA_DIRECTORY) + "import-mce.pptx"; + getComponent() = loadFromDesktop(aURL); + uno::Reference<drawing::XDrawPagesSupplier> xDrawPagesSupplier(getComponent(), uno::UNO_QUERY); + uno::Reference<drawing::XDrawPage> xDrawPage(xDrawPagesSupplier->getDrawPages()->getByIndex(0), + uno::UNO_QUERY); + + // Without the accompanying fix in place, this failed with: + // - Expected: 1 + // - Actual : 2 + // i.e. both the math object and its replacement image was imported, as two separate objects. + CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32>(1), xDrawPage->getCount()); +} + +CPPUNIT_PLUGIN_IMPLEMENT(); + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/oox/qa/unit/shape.cxx b/oox/qa/unit/shape.cxx new file mode 100644 index 000000000..a57c779d0 --- /dev/null +++ b/oox/qa/unit/shape.cxx @@ -0,0 +1,93 @@ +/* -*- 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 <test/bootstrapfixture.hxx> +#include <unotest/macros_test.hxx> + +#include <com/sun/star/drawing/XDrawPagesSupplier.hpp> +#include <com/sun/star/frame/Desktop.hpp> +#include <com/sun/star/beans/XPropertySet.hpp> + +#include <rtl/math.hxx> + +using namespace ::com::sun::star; + +char const DATA_DIRECTORY[] = "/oox/qa/unit/data/"; + +/// oox shape tests. +class OoxShapeTest : public test::BootstrapFixture, public unotest::MacrosTest +{ +private: + uno::Reference<lang::XComponent> mxComponent; + +public: + void setUp() override; + void tearDown() override; + uno::Reference<lang::XComponent>& getComponent() { return mxComponent; } + void load(const OUString& rURL); +}; + +void OoxShapeTest::setUp() +{ + test::BootstrapFixture::setUp(); + + mxDesktop.set(frame::Desktop::create(mxComponentContext)); +} + +void OoxShapeTest::tearDown() +{ + if (mxComponent.is()) + mxComponent->dispose(); + + test::BootstrapFixture::tearDown(); +} + +void OoxShapeTest::load(const OUString& rFileName) +{ + OUString aURL = m_directories.getURLFromSrc(DATA_DIRECTORY) + rFileName; + mxComponent = loadFromDesktop(aURL); +} + +CPPUNIT_TEST_FIXTURE(OoxShapeTest, testMultipleGroupShapes) +{ + load("multiple-group-shapes.docx"); + + uno::Reference<drawing::XDrawPagesSupplier> xDrawPagesSupplier(getComponent(), uno::UNO_QUERY); + uno::Reference<drawing::XDrawPage> xDrawPage(xDrawPagesSupplier->getDrawPages()->getByIndex(0), + uno::UNO_QUERY); + // Without the accompanying fix in place, this test would have failed with: + // - Expected: 2 + // - Actual : 1 + // i.e. the 2 group shapes from the document were imported as a single one. + CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32>(2), xDrawPage->getCount()); +} + +CPPUNIT_TEST_FIXTURE(OoxShapeTest, testCustomshapePosition) +{ + load("customshape-position.docx"); + + uno::Reference<drawing::XDrawPagesSupplier> xDrawPagesSupplier(getComponent(), uno::UNO_QUERY); + uno::Reference<drawing::XDrawPage> xDrawPage(xDrawPagesSupplier->getDrawPages()->getByIndex(0), + uno::UNO_QUERY); + uno::Reference<beans::XPropertySet> xShape(xDrawPage->getByIndex(0), uno::UNO_QUERY); + + sal_Int32 nY{}; + xShape->getPropertyValue("VertOrientPosition") >>= nY; + // <wp:posOffset>581025</wp:posOffset> in the document. + sal_Int32 nExpected = rtl::math::round(581025.0 / 360); + // Without the accompanying fix in place, this test would have failed with: + // - Expected: 1614 + // - Actual : 0 + // i.e. the position of the shape was lost on import due to the rounded corners. + CPPUNIT_ASSERT_EQUAL(nExpected, nY); +} + +CPPUNIT_PLUGIN_IMPLEMENT(); + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/oox/qa/unit/vba_compression.cxx b/oox/qa/unit/vba_compression.cxx new file mode 100644 index 000000000..bfe241c59 --- /dev/null +++ b/oox/qa/unit/vba_compression.cxx @@ -0,0 +1,255 @@ +/* -*- 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 <cppunit/plugin/TestPlugIn.h> +#include <cppunit/extensions/HelperMacros.h> +#include <cppunit/TestFixture.h> +#include <osl/file.hxx> +#include <oox/ole/vbaexport.hxx> +#include <rtl/bootstrap.hxx> +#include <tools/stream.hxx> +#include <unotest/directories.hxx> +#include <algorithm> + +class TestVbaCompression : public CppUnit::TestFixture +{ +public: + // just a sequence of bytes that should not be compressed at all + void testSimple1(); + + // a sequence containing one subsequence that can be compressed + void testSimple2(); + + void testSimple3(); + + // real stream from a document + void testComplex1(); + + // tests taken from the VBA specification + // section 3.2 + + // section 3.2.1 + void testSpec321(); + // section 3.2.2 + void testSpec322(); + // section 3.2.3 + void testSpec323(); + + CPPUNIT_TEST_SUITE(TestVbaCompression); + CPPUNIT_TEST(testSimple1); + CPPUNIT_TEST(testSimple2); + CPPUNIT_TEST(testSimple3); + CPPUNIT_TEST(testComplex1); + CPPUNIT_TEST(testSpec321); + CPPUNIT_TEST(testSpec322); + CPPUNIT_TEST(testSpec323); + CPPUNIT_TEST_SUITE_END(); + +private: + static OUString const & getDebugDirUrl() { + struct DebugDirUrl { + DebugDirUrl() : url("$UserInstallation/debug/") { + rtl::Bootstrap::expandMacros(url); + //TODO: provide an OUString -> OUString expansion function, and which throws on + // failure + auto e = osl::Directory::create(url); + CPPUNIT_ASSERT_EQUAL(osl::FileBase::E_None, e); + } + OUString url; + }; + static DebugDirUrl url; + return url.url; + } + + test::Directories m_directories; +}; + +namespace { + +void ReadFiles(const OUString& rTestFile, const OUString& rReference, + SvMemoryStream& rOutputMemoryStream, SvMemoryStream& rReferenceMemoryStream, + const OUString& rDebugPath) +{ + SvFileStream aInputStream(rTestFile, StreamMode::READ); + SvMemoryStream aInputMemoryStream(4096, 4096); + aInputMemoryStream.WriteStream(aInputStream); + + VBACompression aCompression(rOutputMemoryStream, aInputMemoryStream); + aCompression.write(); + + SvFileStream aReferenceStream(rReference, StreamMode::READ); + rReferenceMemoryStream.WriteStream(aReferenceStream); + + rOutputMemoryStream.Seek(0); + SvFileStream aDebugStream(rDebugPath, StreamMode::WRITE); + aDebugStream.WriteStream(rOutputMemoryStream); +} + +} + +void TestVbaCompression::testSimple1() +{ + OUString aTestFile = m_directories.getPathFromSrc("/oox/qa/unit/data/vba/simple1.bin"); + OUString aReference = m_directories.getPathFromSrc("/oox/qa/unit/data/vba/reference/simple1.bin"); + + SvMemoryStream aOutputMemoryStream(4096, 4096); + SvMemoryStream aReferenceMemoryStream(4096, 4096); + ReadFiles(aTestFile, aReference, aOutputMemoryStream, + aReferenceMemoryStream, getDebugDirUrl() + "vba_debug.bin"); + + CPPUNIT_ASSERT_EQUAL(aReferenceMemoryStream.GetSize(), aOutputMemoryStream.GetSize()); + + const sal_uInt8* pReferenceData = static_cast<const sal_uInt8*>( aReferenceMemoryStream.GetData() ); + const sal_uInt8* pData = static_cast<const sal_uInt8*>( aOutputMemoryStream.GetData() ); + + const sal_uInt64 nSize = std::min(aReferenceMemoryStream.GetSize(), + aOutputMemoryStream.GetSize()); + for (sal_uInt64 i = 0; i < nSize; ++i) + { + CPPUNIT_ASSERT_EQUAL(static_cast<int>(pReferenceData[i]), static_cast<int>(pData[i])); + } +} + +void TestVbaCompression::testSimple2() +{ + OUString aTestFile = m_directories.getPathFromSrc("/oox/qa/unit/data/vba/simple2.bin"); + OUString aReference = m_directories.getPathFromSrc("/oox/qa/unit/data/vba/reference/simple2.bin"); + + SvMemoryStream aOutputMemoryStream(4096, 4096); + SvMemoryStream aReferenceMemoryStream(4096, 4096); + ReadFiles(aTestFile, aReference, aOutputMemoryStream, aReferenceMemoryStream, getDebugDirUrl() + "vba_debug2.bin"); + + CPPUNIT_ASSERT_EQUAL(aReferenceMemoryStream.GetSize(), aOutputMemoryStream.GetSize()); + + const sal_uInt8* pReferenceData = static_cast<const sal_uInt8*>( aReferenceMemoryStream.GetData() ); + const sal_uInt8* pData = static_cast<const sal_uInt8*>( aOutputMemoryStream.GetData() ); + + const sal_uInt64 nSize = std::min(aReferenceMemoryStream.GetSize(), + aOutputMemoryStream.GetSize()); + for (sal_uInt64 i = 0; i < nSize; ++i) + { + CPPUNIT_ASSERT_EQUAL(static_cast<int>(pReferenceData[i]), static_cast<int>(pData[i])); + } +} + +void TestVbaCompression::testSimple3() +{ + OUString aTestFile = m_directories.getPathFromSrc("/oox/qa/unit/data/vba/simple3.bin"); + OUString aReference = m_directories.getPathFromSrc("/oox/qa/unit/data/vba/reference/simple3.bin"); + + SvMemoryStream aOutputMemoryStream(4096, 4096); + SvMemoryStream aReferenceMemoryStream(4096, 4096); + ReadFiles(aTestFile, aReference, aOutputMemoryStream, aReferenceMemoryStream, getDebugDirUrl() + "vba_debug3.bin"); + + CPPUNIT_ASSERT_EQUAL(aReferenceMemoryStream.GetSize(), aOutputMemoryStream.GetSize()); + + const sal_uInt8* pReferenceData = static_cast<const sal_uInt8*>( aReferenceMemoryStream.GetData() ); + const sal_uInt8* pData = static_cast<const sal_uInt8*>( aOutputMemoryStream.GetData() ); + + const sal_uInt64 nSize = std::min(aReferenceMemoryStream.GetSize(), + aOutputMemoryStream.GetSize()); + for (sal_uInt64 i = 0; i < nSize; ++i) + { + CPPUNIT_ASSERT_EQUAL(static_cast<int>(pReferenceData[i]), static_cast<int>(pData[i])); + } +} + +void TestVbaCompression::testComplex1() +{ + OUString aTestFile = m_directories.getPathFromSrc("/oox/qa/unit/data/vba/complex1.bin"); + OUString aReference = m_directories.getPathFromSrc("/oox/qa/unit/data/vba/reference/complex1.bin"); + + SvMemoryStream aOutputMemoryStream(4096, 4096); + SvMemoryStream aReferenceMemoryStream(4096, 4096); + ReadFiles(aTestFile, aReference, aOutputMemoryStream, aReferenceMemoryStream, getDebugDirUrl() + "vba_debug_complex1.bin"); + + CPPUNIT_ASSERT_EQUAL(aReferenceMemoryStream.GetSize(), aOutputMemoryStream.GetSize()); + + const sal_uInt8* pReferenceData = static_cast<const sal_uInt8*>( aReferenceMemoryStream.GetData() ); + const sal_uInt8* pData = static_cast<const sal_uInt8*>( aOutputMemoryStream.GetData() ); + + const sal_uInt64 nSize = std::min(aReferenceMemoryStream.GetSize(), + aOutputMemoryStream.GetSize()); + for (sal_uInt64 i = 0; i < nSize; ++i) + { + CPPUNIT_ASSERT_EQUAL(static_cast<int>(pReferenceData[i]), static_cast<int>(pData[i])); + } +} + +void TestVbaCompression::testSpec321() +{ + OUString aTestFile = m_directories.getPathFromSrc("/oox/qa/unit/data/vba/spec321.bin"); + OUString aReference = m_directories.getPathFromSrc("/oox/qa/unit/data/vba/reference/spec321.bin"); + + SvMemoryStream aOutputMemoryStream(4096, 4096); + SvMemoryStream aReferenceMemoryStream(4096, 4096); + ReadFiles(aTestFile, aReference, aOutputMemoryStream, aReferenceMemoryStream, getDebugDirUrl() + "vba_debug_spec321.bin"); + + CPPUNIT_ASSERT_EQUAL(aReferenceMemoryStream.GetSize(), aOutputMemoryStream.GetSize()); + + const sal_uInt8* pReferenceData = static_cast<const sal_uInt8*>( aReferenceMemoryStream.GetData() ); + const sal_uInt8* pData = static_cast<const sal_uInt8*>( aOutputMemoryStream.GetData() ); + + const sal_uInt64 nSize = std::min(aReferenceMemoryStream.GetSize(), + aOutputMemoryStream.GetSize()); + for (sal_uInt64 i = 0; i < nSize; ++i) + { + CPPUNIT_ASSERT_EQUAL(static_cast<int>(pReferenceData[i]), static_cast<int>(pData[i])); + } +} + +void TestVbaCompression::testSpec322() +{ + OUString aTestFile = m_directories.getPathFromSrc("/oox/qa/unit/data/vba/spec322.bin"); + OUString aReference = m_directories.getPathFromSrc("/oox/qa/unit/data/vba/reference/spec322.bin"); + + SvMemoryStream aOutputMemoryStream(4096, 4096); + SvMemoryStream aReferenceMemoryStream(4096, 4096); + ReadFiles(aTestFile, aReference, aOutputMemoryStream, aReferenceMemoryStream, getDebugDirUrl() + "vba_debug_spec322.bin"); + + CPPUNIT_ASSERT_EQUAL(aReferenceMemoryStream.GetSize(), aOutputMemoryStream.GetSize()); + + const sal_uInt8* pReferenceData = static_cast<const sal_uInt8*>( aReferenceMemoryStream.GetData() ); + const sal_uInt8* pData = static_cast<const sal_uInt8*>( aOutputMemoryStream.GetData() ); + + const sal_uInt64 nSize = std::min(aReferenceMemoryStream.GetSize(), + aOutputMemoryStream.GetSize()); + for (sal_uInt64 i = 0; i < nSize; ++i) + { + CPPUNIT_ASSERT_EQUAL(static_cast<int>(pReferenceData[i]), static_cast<int>(pData[i])); + } +} + +void TestVbaCompression::testSpec323() +{ + OUString aTestFile = m_directories.getPathFromSrc("/oox/qa/unit/data/vba/spec323.bin"); + OUString aReference = m_directories.getPathFromSrc("/oox/qa/unit/data/vba/reference/spec323.bin"); + + SvMemoryStream aOutputMemoryStream(4096, 4096); + SvMemoryStream aReferenceMemoryStream(4096, 4096); + ReadFiles(aTestFile, aReference, aOutputMemoryStream, aReferenceMemoryStream, getDebugDirUrl() + "vba_debug_spec323.bin"); + + CPPUNIT_ASSERT_EQUAL(aReferenceMemoryStream.GetSize(), aOutputMemoryStream.GetSize()); + + const sal_uInt8* pReferenceData = static_cast<const sal_uInt8*>( aReferenceMemoryStream.GetData() ); + const sal_uInt8* pData = static_cast<const sal_uInt8*>( aOutputMemoryStream.GetData() ); + + const sal_uInt64 nSize = std::min(aReferenceMemoryStream.GetSize(), + aOutputMemoryStream.GetSize()); + for (sal_uInt64 i = 0; i < nSize; ++i) + { + CPPUNIT_ASSERT_EQUAL(static_cast<int>(pReferenceData[i]), static_cast<int>(pData[i])); + } +} + +CPPUNIT_TEST_SUITE_REGISTRATION(TestVbaCompression); + +CPPUNIT_PLUGIN_IMPLEMENT(); + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/oox/qa/unit/vba_encryption.cxx b/oox/qa/unit/vba_encryption.cxx new file mode 100644 index 000000000..7e8a44cd9 --- /dev/null +++ b/oox/qa/unit/vba_encryption.cxx @@ -0,0 +1,85 @@ +/* -*- 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 <cppunit/plugin/TestPlugIn.h> +#include <cppunit/extensions/HelperMacros.h> +#include <cppunit/TestFixture.h> + +#include <oox/ole/vbaexport.hxx> +#include <algorithm> + +class TestVbaEncryption : public CppUnit::TestFixture +{ +public: + +#if 0 + // an initial test for the encryption taken from the spec + void testSimple1(); + + void testSimple2(); +#endif + + void testProjKey1(); + + CPPUNIT_TEST_SUITE(TestVbaEncryption); + // CPPUNIT_TEST(testSimple1); + // CPPUNIT_TEST(testSimple2); + CPPUNIT_TEST(testProjKey1); + CPPUNIT_TEST_SUITE_END(); +}; + +#if 0 +void TestVbaEncryption::testSimple1() +{ + sal_uInt8 nSeed = 0x07; + sal_uInt8 nProjKey = 0xDF; + sal_uInt16 nLength = 0x04; + sal_uInt8 pData[] = { 0x00, 0x00, 0x00, 0x00 }; + + SvMemoryStream aEncryptedStream(4096, 4096); + VBAEncryption aEncryption(pData, nLength, aEncryptedStream, + &nSeed, nProjKey); + aEncryption.write(); +} + +void TestVbaEncryption::testSimple2() +{ + sal_uInt8 nSeed = 0x15; + sal_uInt8 nProjKey = 0xDF; + sal_uInt16 nLength = 0x01; + sal_uInt8 pData[] = { 0xFF }; + + SvMemoryStream aEncryptedStream(4096, 4096); + VBAEncryption aEncryption(pData, nLength, aEncryptedStream, + &nSeed, nProjKey); + aEncryption.write(); + sal_uInt8 pExpectedData[] = "1517CAF1D6F9D7F9D706"; + size_t length = sizeof(pExpectedData); + aEncryptedStream.Seek(0); + for (size_t i = 0; i < length; ++i) + { + unsigned char val = 0; + aEncryptedStream.ReadUChar(val); + CPPUNIT_ASSERT_EQUAL((int)pExpectedData[i], (int)sal_uInt8(val)); + } +} +#endif + +void TestVbaEncryption::testProjKey1() +{ + OUString const aProjectID("{917DED54-440B-4FD1-A5C1-74ACF261E600}"); + sal_uInt8 nProjKey = VBAEncryption::calculateProjKey(aProjectID); + CPPUNIT_ASSERT_EQUAL(int(0xdf), static_cast<int>(nProjKey)); +} + +CPPUNIT_TEST_SUITE_REGISTRATION(TestVbaEncryption); + +CPPUNIT_PLUGIN_IMPLEMENT(); + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/oox/qa/unit/vml.cxx b/oox/qa/unit/vml.cxx new file mode 100644 index 000000000..d43d2d564 --- /dev/null +++ b/oox/qa/unit/vml.cxx @@ -0,0 +1,146 @@ +/* -*- 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 <test/bootstrapfixture.hxx> +#include <unotest/macros_test.hxx> + +#include <com/sun/star/beans/XPropertySet.hpp> +#include <com/sun/star/drawing/LineStyle.hpp> +#include <com/sun/star/drawing/XDrawPagesSupplier.hpp> +#include <com/sun/star/frame/Desktop.hpp> +#include <com/sun/star/lang/XServiceInfo.hpp> +#include <com/sun/star/text/WritingMode2.hpp> + +using namespace ::com::sun::star; + +char const DATA_DIRECTORY[] = "/oox/qa/unit/data/"; + +/// oox vml tests. +class OoxVmlTest : public test::BootstrapFixture, public unotest::MacrosTest +{ +private: + uno::Reference<lang::XComponent> mxComponent; + +public: + void setUp() override; + void tearDown() override; + uno::Reference<lang::XComponent>& getComponent() { return mxComponent; } + void load(const OUString& rURL); +}; + +void OoxVmlTest::setUp() +{ + test::BootstrapFixture::setUp(); + + mxDesktop.set(frame::Desktop::create(mxComponentContext)); +} + +void OoxVmlTest::tearDown() +{ + if (mxComponent.is()) + mxComponent->dispose(); + + test::BootstrapFixture::tearDown(); +} + +void OoxVmlTest::load(const OUString& rFileName) +{ + OUString aURL = m_directories.getURLFromSrc(DATA_DIRECTORY) + rFileName; + mxComponent = loadFromDesktop(aURL); +} + +CPPUNIT_TEST_FIXTURE(OoxVmlTest, testLayoutFlowAltAlone) +{ + // mso-layout-flow-alt:bottom-to-top without a matching layout-flow:vertical. + load("layout-flow-alt-alone.docx"); + + uno::Reference<drawing::XDrawPagesSupplier> xDrawPagesSupplier(getComponent(), uno::UNO_QUERY); + uno::Reference<drawing::XDrawPage> xDrawPage(xDrawPagesSupplier->getDrawPages()->getByIndex(0), + uno::UNO_QUERY); + uno::Reference<beans::XPropertySet> xShape(xDrawPage->getByIndex(0), uno::UNO_QUERY); + sal_Int16 nWritingMode = 0; + xShape->getPropertyValue("WritingMode") >>= nWritingMode; + + // Without the accompanying fix in place, this test would have failed with: + // - Expected: 5 [ BTLR ] + // - Actual : 4 [ PAGE ] + // i.e. in case layout-flow:vertical was missing, the text was not vertical. + CPPUNIT_ASSERT_EQUAL(text::WritingMode2::BT_LR, nWritingMode); +} + +CPPUNIT_TEST_FIXTURE(OoxVmlTest, testSpt202ShapeType) +{ + // Load a document with a groupshape, 2nd child is a <v:shape>, its type has o:spt set to 202 + // (TextBox). + load("group-spt202.docx"); + uno::Reference<drawing::XDrawPagesSupplier> xDrawPagesSupplier(getComponent(), uno::UNO_QUERY); + uno::Reference<drawing::XDrawPage> xDrawPage(xDrawPagesSupplier->getDrawPages()->getByIndex(0), + uno::UNO_QUERY); + uno::Reference<container::XIndexAccess> xGroup(xDrawPage->getByIndex(0), uno::UNO_QUERY); + uno::Reference<drawing::XShape> xShape(xGroup->getByIndex(1), uno::UNO_QUERY); + + // Without the accompanying fix in place, this test would have failed with: + // - Expected: com.sun.star.drawing.TextShape + // - Actual : com.sun.star.drawing.CustomShape + // and then the size of the group shape was incorrect, e.g. its right edge was outside the page + // boundaries. + CPPUNIT_ASSERT_EQUAL(OUString("com.sun.star.drawing.TextShape"), xShape->getShapeType()); +} + +CPPUNIT_TEST_FIXTURE(OoxVmlTest, testShapeNonAutosizeWithText) +{ + // Load a document which has a group shape, containing a single child. + // 17.78 cm is the full group shape width, 19431/64008 is the child shape's relative width inside + // that, so 5.3975 cm should be the shape width. + load("shape-non-autosize-with-text.docx"); + uno::Reference<drawing::XDrawPagesSupplier> xDrawPagesSupplier(getComponent(), uno::UNO_QUERY); + uno::Reference<drawing::XDrawPage> xDrawPage(xDrawPagesSupplier->getDrawPages()->getByIndex(0), + uno::UNO_QUERY); + uno::Reference<container::XIndexAccess> xGroup(xDrawPage->getByIndex(0), uno::UNO_QUERY); + uno::Reference<drawing::XShape> xShape(xGroup->getByIndex(0), uno::UNO_QUERY); + // Without the accompanying fix in place, this test would have failed with: + // - Actual : 1115 + // - Expected: 5398 + // because the width was determined using its text size, not using the explicit size. + CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32>(5398), xShape->getSize().Width); +} + +CPPUNIT_TEST_FIXTURE(OoxVmlTest, testGraphicStroke) +{ + load("graphic-stroke.pptx"); + uno::Reference<drawing::XDrawPagesSupplier> xDrawPagesSupplier(getComponent(), uno::UNO_QUERY); + uno::Reference<drawing::XDrawPage> xDrawPage(xDrawPagesSupplier->getDrawPages()->getByIndex(0), + uno::UNO_QUERY); + + uno::Reference<beans::XPropertySet> xShape; + for (sal_Int32 i = 0; i < xDrawPage->getCount(); ++i) + { + uno::Reference<lang::XServiceInfo> xInfo(xDrawPage->getByIndex(i), uno::UNO_QUERY); + if (!xInfo->supportsService("com.sun.star.drawing.GraphicObjectShape")) + { + continue; + } + + xShape.set(xInfo, uno::UNO_QUERY); + break; + } + CPPUNIT_ASSERT(xShape.is()); + + drawing::LineStyle eLineStyle{}; + xShape->getPropertyValue("LineStyle") >>= eLineStyle; + // Without the accompanying fix in place, this test would have failed with: + // - Expected: 1 + // - Actual : 0 + // i.e. line style was NONE, not SOLID. + CPPUNIT_ASSERT_EQUAL(drawing::LineStyle_SOLID, eLineStyle); +} + +CPPUNIT_PLUGIN_IMPLEMENT(); + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |