1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3  * This file is part of the LibreOffice project.
4  *
5  * This Source Code Form is subject to the terms of the Mozilla Public
6  * License, v. 2.0. If a copy of the MPL was not distributed with this
7  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8  */
9 
10 #include <cppunit/plugin/TestPlugIn.h>
11 #include <cppunit/extensions/HelperMacros.h>
12 #include <cppunit/TestFixture.h>
13 #include <osl/file.hxx>
14 #include <oox/ole/vbaexport.hxx>
15 #include <rtl/bootstrap.hxx>
16 #include <tools/stream.hxx>
17 #include <unotest/directories.hxx>
18 #include <algorithm>
19 
20 class TestVbaCompression : public CppUnit::TestFixture
21 {
22 public:
23     // just a sequence of bytes that should not be compressed at all
24     void testSimple1();
25 
26     // a sequence containing one subsequence that can be compressed
27     void testSimple2();
28 
29     void testSimple3();
30 
31     // real stream from a document
32     void testComplex1();
33 
34     // tests taken from the VBA specification
35     // section 3.2
36 
37     // section 3.2.1
38     void testSpec321();
39     // section 3.2.2
40     void testSpec322();
41     // section 3.2.3
42     void testSpec323();
43 
44     CPPUNIT_TEST_SUITE(TestVbaCompression);
45     CPPUNIT_TEST(testSimple1);
46     CPPUNIT_TEST(testSimple2);
47     CPPUNIT_TEST(testSimple3);
48     CPPUNIT_TEST(testComplex1);
49     CPPUNIT_TEST(testSpec321);
50     CPPUNIT_TEST(testSpec322);
51     CPPUNIT_TEST(testSpec323);
52     CPPUNIT_TEST_SUITE_END();
53 
54 private:
getDebugDirUrl()55     static OUString const & getDebugDirUrl() {
56         struct DebugDirUrl {
57             DebugDirUrl() : url("$UserInstallation/debug/") {
58                 rtl::Bootstrap::expandMacros(url);
59                     //TODO: provide an OUString -> OUString expansion function, and which throws on
60                     // failure
61                 auto e = osl::Directory::create(url);
62                 CPPUNIT_ASSERT_EQUAL(osl::FileBase::E_None, e);
63             }
64             OUString url;
65         };
66         static DebugDirUrl url;
67         return url.url;
68     }
69 
70     test::Directories m_directories;
71 };
72 
73 namespace {
74 
ReadFiles(const OUString & rTestFile,const OUString & rReference,SvMemoryStream & rOutputMemoryStream,SvMemoryStream & rReferenceMemoryStream,const OUString & rDebugPath)75 void ReadFiles(const OUString& rTestFile, const OUString& rReference,
76         SvMemoryStream& rOutputMemoryStream, SvMemoryStream& rReferenceMemoryStream,
77         const OUString& rDebugPath)
78 {
79     SvFileStream aInputStream(rTestFile, StreamMode::READ);
80     SvMemoryStream aInputMemoryStream(4096, 4096);
81     aInputMemoryStream.WriteStream(aInputStream);
82 
83     VBACompression aCompression(rOutputMemoryStream, aInputMemoryStream);
84     aCompression.write();
85 
86     SvFileStream aReferenceStream(rReference, StreamMode::READ);
87     rReferenceMemoryStream.WriteStream(aReferenceStream);
88 
89     rOutputMemoryStream.Seek(0);
90     SvFileStream aDebugStream(rDebugPath, StreamMode::WRITE);
91     aDebugStream.WriteStream(rOutputMemoryStream);
92 }
93 
94 }
95 
testSimple1()96 void TestVbaCompression::testSimple1()
97 {
98     OUString aTestFile = m_directories.getPathFromSrc(u"/oox/qa/unit/data/vba/simple1.bin");
99     OUString aReference = m_directories.getPathFromSrc(u"/oox/qa/unit/data/vba/reference/simple1.bin");
100 
101     SvMemoryStream aOutputMemoryStream(4096, 4096);
102     SvMemoryStream aReferenceMemoryStream(4096, 4096);
103     ReadFiles(aTestFile, aReference, aOutputMemoryStream,
104             aReferenceMemoryStream, getDebugDirUrl() + "vba_debug.bin");
105 
106     CPPUNIT_ASSERT_EQUAL(aReferenceMemoryStream.GetSize(), aOutputMemoryStream.GetSize());
107 
108     const sal_uInt8* pReferenceData = static_cast<const sal_uInt8*>( aReferenceMemoryStream.GetData() );
109     const sal_uInt8* pData = static_cast<const sal_uInt8*>( aOutputMemoryStream.GetData() );
110 
111     const sal_uInt64 nSize = std::min(aReferenceMemoryStream.GetSize(),
112             aOutputMemoryStream.GetSize());
113     for (sal_uInt64 i = 0; i < nSize; ++i)
114     {
115         CPPUNIT_ASSERT_EQUAL(static_cast<int>(pReferenceData[i]), static_cast<int>(pData[i]));
116     }
117 }
118 
testSimple2()119 void TestVbaCompression::testSimple2()
120 {
121     OUString aTestFile = m_directories.getPathFromSrc(u"/oox/qa/unit/data/vba/simple2.bin");
122     OUString aReference = m_directories.getPathFromSrc(u"/oox/qa/unit/data/vba/reference/simple2.bin");
123 
124     SvMemoryStream aOutputMemoryStream(4096, 4096);
125     SvMemoryStream aReferenceMemoryStream(4096, 4096);
126     ReadFiles(aTestFile, aReference, aOutputMemoryStream, aReferenceMemoryStream, getDebugDirUrl() + "vba_debug2.bin");
127 
128     CPPUNIT_ASSERT_EQUAL(aReferenceMemoryStream.GetSize(), aOutputMemoryStream.GetSize());
129 
130     const sal_uInt8* pReferenceData = static_cast<const sal_uInt8*>( aReferenceMemoryStream.GetData() );
131     const sal_uInt8* pData = static_cast<const sal_uInt8*>( aOutputMemoryStream.GetData() );
132 
133     const sal_uInt64 nSize = std::min(aReferenceMemoryStream.GetSize(),
134             aOutputMemoryStream.GetSize());
135     for (sal_uInt64 i = 0; i < nSize; ++i)
136     {
137         CPPUNIT_ASSERT_EQUAL(static_cast<int>(pReferenceData[i]), static_cast<int>(pData[i]));
138     }
139 }
140 
testSimple3()141 void TestVbaCompression::testSimple3()
142 {
143     OUString aTestFile = m_directories.getPathFromSrc(u"/oox/qa/unit/data/vba/simple3.bin");
144     OUString aReference = m_directories.getPathFromSrc(u"/oox/qa/unit/data/vba/reference/simple3.bin");
145 
146     SvMemoryStream aOutputMemoryStream(4096, 4096);
147     SvMemoryStream aReferenceMemoryStream(4096, 4096);
148     ReadFiles(aTestFile, aReference, aOutputMemoryStream, aReferenceMemoryStream, getDebugDirUrl() + "vba_debug3.bin");
149 
150     CPPUNIT_ASSERT_EQUAL(aReferenceMemoryStream.GetSize(), aOutputMemoryStream.GetSize());
151 
152     const sal_uInt8* pReferenceData = static_cast<const sal_uInt8*>( aReferenceMemoryStream.GetData()  );
153     const sal_uInt8* pData = static_cast<const sal_uInt8*>( aOutputMemoryStream.GetData() );
154 
155     const sal_uInt64 nSize = std::min(aReferenceMemoryStream.GetSize(),
156             aOutputMemoryStream.GetSize());
157     for (sal_uInt64 i = 0; i < nSize; ++i)
158     {
159         CPPUNIT_ASSERT_EQUAL(static_cast<int>(pReferenceData[i]), static_cast<int>(pData[i]));
160     }
161 }
162 
testComplex1()163 void TestVbaCompression::testComplex1()
164 {
165     OUString aTestFile = m_directories.getPathFromSrc(u"/oox/qa/unit/data/vba/complex1.bin");
166     OUString aReference = m_directories.getPathFromSrc(u"/oox/qa/unit/data/vba/reference/complex1.bin");
167 
168     SvMemoryStream aOutputMemoryStream(4096, 4096);
169     SvMemoryStream aReferenceMemoryStream(4096, 4096);
170     ReadFiles(aTestFile, aReference, aOutputMemoryStream, aReferenceMemoryStream, getDebugDirUrl() + "vba_debug_complex1.bin");
171 
172     CPPUNIT_ASSERT_EQUAL(aReferenceMemoryStream.GetSize(), aOutputMemoryStream.GetSize());
173 
174     const sal_uInt8* pReferenceData = static_cast<const sal_uInt8*>( aReferenceMemoryStream.GetData() );
175     const sal_uInt8* pData = static_cast<const sal_uInt8*>( aOutputMemoryStream.GetData() );
176 
177     const sal_uInt64 nSize = std::min(aReferenceMemoryStream.GetSize(),
178             aOutputMemoryStream.GetSize());
179     for (sal_uInt64 i = 0; i < nSize; ++i)
180     {
181         CPPUNIT_ASSERT_EQUAL(static_cast<int>(pReferenceData[i]), static_cast<int>(pData[i]));
182     }
183 }
184 
testSpec321()185 void TestVbaCompression::testSpec321()
186 {
187     OUString aTestFile = m_directories.getPathFromSrc(u"/oox/qa/unit/data/vba/spec321.bin");
188     OUString aReference = m_directories.getPathFromSrc(u"/oox/qa/unit/data/vba/reference/spec321.bin");
189 
190     SvMemoryStream aOutputMemoryStream(4096, 4096);
191     SvMemoryStream aReferenceMemoryStream(4096, 4096);
192     ReadFiles(aTestFile, aReference, aOutputMemoryStream, aReferenceMemoryStream, getDebugDirUrl() + "vba_debug_spec321.bin");
193 
194     CPPUNIT_ASSERT_EQUAL(aReferenceMemoryStream.GetSize(), aOutputMemoryStream.GetSize());
195 
196     const sal_uInt8* pReferenceData = static_cast<const sal_uInt8*>( aReferenceMemoryStream.GetData() );
197     const sal_uInt8* pData = static_cast<const sal_uInt8*>( aOutputMemoryStream.GetData() );
198 
199     const sal_uInt64 nSize = std::min(aReferenceMemoryStream.GetSize(),
200             aOutputMemoryStream.GetSize());
201     for (sal_uInt64 i = 0; i < nSize; ++i)
202     {
203         CPPUNIT_ASSERT_EQUAL(static_cast<int>(pReferenceData[i]), static_cast<int>(pData[i]));
204     }
205 }
206 
testSpec322()207 void TestVbaCompression::testSpec322()
208 {
209     OUString aTestFile = m_directories.getPathFromSrc(u"/oox/qa/unit/data/vba/spec322.bin");
210     OUString aReference = m_directories.getPathFromSrc(u"/oox/qa/unit/data/vba/reference/spec322.bin");
211 
212     SvMemoryStream aOutputMemoryStream(4096, 4096);
213     SvMemoryStream aReferenceMemoryStream(4096, 4096);
214     ReadFiles(aTestFile, aReference, aOutputMemoryStream, aReferenceMemoryStream, getDebugDirUrl() + "vba_debug_spec322.bin");
215 
216     CPPUNIT_ASSERT_EQUAL(aReferenceMemoryStream.GetSize(), aOutputMemoryStream.GetSize());
217 
218     const sal_uInt8* pReferenceData = static_cast<const sal_uInt8*>( aReferenceMemoryStream.GetData() );
219     const sal_uInt8* pData = static_cast<const sal_uInt8*>( aOutputMemoryStream.GetData() );
220 
221     const sal_uInt64 nSize = std::min(aReferenceMemoryStream.GetSize(),
222             aOutputMemoryStream.GetSize());
223     for (sal_uInt64 i = 0; i < nSize; ++i)
224     {
225         CPPUNIT_ASSERT_EQUAL(static_cast<int>(pReferenceData[i]), static_cast<int>(pData[i]));
226     }
227 }
228 
testSpec323()229 void TestVbaCompression::testSpec323()
230 {
231     OUString aTestFile = m_directories.getPathFromSrc(u"/oox/qa/unit/data/vba/spec323.bin");
232     OUString aReference = m_directories.getPathFromSrc(u"/oox/qa/unit/data/vba/reference/spec323.bin");
233 
234     SvMemoryStream aOutputMemoryStream(4096, 4096);
235     SvMemoryStream aReferenceMemoryStream(4096, 4096);
236     ReadFiles(aTestFile, aReference, aOutputMemoryStream, aReferenceMemoryStream, getDebugDirUrl() + "vba_debug_spec323.bin");
237 
238     CPPUNIT_ASSERT_EQUAL(aReferenceMemoryStream.GetSize(), aOutputMemoryStream.GetSize());
239 
240     const sal_uInt8* pReferenceData = static_cast<const sal_uInt8*>( aReferenceMemoryStream.GetData() );
241     const sal_uInt8* pData = static_cast<const sal_uInt8*>( aOutputMemoryStream.GetData() );
242 
243     const sal_uInt64 nSize = std::min(aReferenceMemoryStream.GetSize(),
244             aOutputMemoryStream.GetSize());
245     for (sal_uInt64 i = 0; i < nSize; ++i)
246     {
247         CPPUNIT_ASSERT_EQUAL(static_cast<int>(pReferenceData[i]), static_cast<int>(pData[i]));
248     }
249 }
250 
251 CPPUNIT_TEST_SUITE_REGISTRATION(TestVbaCompression);
252 
253 CPPUNIT_PLUGIN_IMPLEMENT();
254 
255 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
256