1 //-*****************************************************************************
2 //
3 // Copyright (c) 2013,
4 //  Sony Pictures Imageworks Inc. and
5 //  Industrial Light & Magic, a division of Lucasfilm Entertainment Company Ltd.
6 //
7 // All rights reserved.
8 //
9 // Redistribution and use in source and binary forms, with or without
10 // modification, are permitted provided that the following conditions are
11 // met:
12 // *       Redistributions of source code must retain the above copyright
13 // notice, this list of conditions and the following disclaimer.
14 // *       Redistributions in binary form must reproduce the above
15 // copyright notice, this list of conditions and the following disclaimer
16 // in the documentation and/or other materials provided with the
17 // distribution.
18 // *       Neither the name of Sony Pictures Imageworks, nor
19 // Industrial Light & Magic, nor the names of their contributors may be used
20 // to endorse or promote products derived from this software without specific
21 // prior written permission.
22 //
23 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
24 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
25 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
26 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
27 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
28 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
29 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
30 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
31 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
33 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34 //
35 //-*****************************************************************************
36 
37 #include <Alembic/AbcCoreAbstract/All.h>
38 #include <Alembic/AbcCoreOgawa/All.h>
39 #include <Alembic/Util/All.h>
40 
41 #include <Alembic/AbcCoreAbstract/Tests/Assert.h>
42 
43 #include <iostream>
44 #include <vector>
45 
46 //-*****************************************************************************
47 namespace AO = Alembic::AbcCoreOgawa;
48 
49 namespace ABCA = Alembic::AbcCoreAbstract;
testArrayPropHashes(bool iUseMMap)50 void testArrayPropHashes(bool iUseMMap)
51 {
52     std::string archiveName = "arrayHashTest.abc";
53     {
54         AO::WriteArchive w;
55         ABCA::ArchiveWriterPtr a = w(archiveName, ABCA::MetaData());
56         ABCA::ObjectWriterPtr archive = a->getTop();
57         ABCA::ObjectWriterPtr child;
58 
59         // add a time sampling for later use
60         std::vector < double > timeSamps(1,-4.0);
61         ABCA::TimeSamplingType tst(3.0);
62         ABCA::TimeSampling ts(tst, timeSamps);
63         a->addTimeSampling(ts);
64 
65         // 2 objects without any properties whatsoever
66         archive->createChild(ABCA::ObjectHeader("emptyA", ABCA::MetaData()));
67         archive->createChild(ABCA::ObjectHeader("emptyB", ABCA::MetaData()));
68 
69         // 2 objects with with the same property with no samples
70         child = archive->createChild(ABCA::ObjectHeader(
71             "1propA", ABCA::MetaData()));
72         child->getProperties()->createArrayProperty("empty",  ABCA::MetaData(),
73             ABCA::DataType(Alembic::Util::kInt32POD, 1), 0);
74 
75         child = archive->createChild(ABCA::ObjectHeader(
76             "1propB", ABCA::MetaData()));
77         child->getProperties()->createArrayProperty("empty",  ABCA::MetaData(),
78             ABCA::DataType(Alembic::Util::kInt32POD, 1), 0);
79 
80         // 2 objects with with the same property with a differnt name from above
81         child = archive->createChild(ABCA::ObjectHeader(
82             "1propAName", ABCA::MetaData()));
83         child->getProperties()->createArrayProperty("null",  ABCA::MetaData(),
84             ABCA::DataType(Alembic::Util::kInt32POD, 1), 0);
85 
86         child = archive->createChild(ABCA::ObjectHeader(
87             "1propBName", ABCA::MetaData()));
88         child->getProperties()->createArrayProperty("null",  ABCA::MetaData(),
89             ABCA::DataType(Alembic::Util::kInt32POD, 1), 0);
90 
91         // 2 objects with with the same property with a differnt MetaData
92         ABCA::MetaData m;
93         m.set("Bleep", "bloop");
94         child = archive->createChild(ABCA::ObjectHeader(
95             "1propAMeta", ABCA::MetaData()));
96         child->getProperties()->createArrayProperty("empty", m,
97             ABCA::DataType(Alembic::Util::kInt32POD, 1), 0);
98 
99         child = archive->createChild(ABCA::ObjectHeader(
100             "1propBMeta", ABCA::MetaData()));
101         child->getProperties()->createArrayProperty("empty", m,
102             ABCA::DataType(Alembic::Util::kInt32POD, 1), 0);
103 
104         // 2 objects with with the same property with a different POD
105         child = archive->createChild(ABCA::ObjectHeader(
106             "1propAPod", ABCA::MetaData()));
107         child->getProperties()->createArrayProperty("empty",  ABCA::MetaData(),
108             ABCA::DataType(Alembic::Util::kFloat32POD, 1), 0);
109 
110         child = archive->createChild(ABCA::ObjectHeader(
111             "1propBPod", ABCA::MetaData()));
112         child->getProperties()->createArrayProperty("empty",  ABCA::MetaData(),
113             ABCA::DataType(Alembic::Util::kFloat32POD, 1), 0);
114 
115         // 2 objects with with the same property with a different extent
116         child = archive->createChild(ABCA::ObjectHeader(
117             "1propAExtent", ABCA::MetaData()));
118         child->getProperties()->createArrayProperty("empty",  ABCA::MetaData(),
119             ABCA::DataType(Alembic::Util::kInt32POD, 2), 0);
120 
121         child = archive->createChild(ABCA::ObjectHeader(
122             "1propBExtent", ABCA::MetaData()));
123         child->getProperties()->createArrayProperty("empty",  ABCA::MetaData(),
124             ABCA::DataType(Alembic::Util::kInt32POD, 2), 0);
125 
126         // 2 objects with with the same property with a differnt time sampling
127         child = archive->createChild(ABCA::ObjectHeader(
128             "1propATS", ABCA::MetaData()));
129         child->getProperties()->createArrayProperty("empty",  ABCA::MetaData(),
130             ABCA::DataType(Alembic::Util::kInt32POD, 1), 1);
131 
132         child = archive->createChild(ABCA::ObjectHeader(
133             "1propBTS", ABCA::MetaData()));
134         child->getProperties()->createArrayProperty("empty",  ABCA::MetaData(),
135             ABCA::DataType(Alembic::Util::kInt32POD, 1), 1);
136 
137         // 2 objects with 1 sample
138         ABCA::ArrayPropertyWriterPtr awp;
139         std::vector <Alembic::Util::int32_t> vali(4, 0);
140         Alembic::Util::Dimensions dims(4);
141         ABCA::DataType i32d(Alembic::Util::kInt32POD, 1);
142 
143         child = archive->createChild(ABCA::ObjectHeader(
144             "1propA1Samp", ABCA::MetaData()));
145         awp = child->getProperties()->createArrayProperty("int",
146             ABCA::MetaData(), ABCA::DataType(Alembic::Util::kInt32POD, 1), 0);
147         awp->setSample(ABCA::ArraySample(&(vali.front()), i32d, dims));
148 
149         child = archive->createChild(ABCA::ObjectHeader(
150             "1propB1Samp", ABCA::MetaData()));
151         awp = child->getProperties()->createArrayProperty("int",
152             ABCA::MetaData(), ABCA::DataType(Alembic::Util::kInt32POD, 1), 0);
153         awp->setSample(ABCA::ArraySample(&(vali.front()), i32d, dims));
154 
155         // 2 objects with 2 samples, no repeats
156         std::vector <Alembic::Util::int32_t> valiB(4, 1);
157 
158         child = archive->createChild(ABCA::ObjectHeader(
159             "1propA2Samp", ABCA::MetaData()));
160         awp = child->getProperties()->createArrayProperty("int",
161             ABCA::MetaData(), ABCA::DataType(Alembic::Util::kInt32POD, 1), 0);
162         awp->setSample(ABCA::ArraySample(&(vali.front()), i32d, dims));
163         awp->setSample(ABCA::ArraySample(&(valiB.front()), i32d, dims));
164 
165         child = archive->createChild(ABCA::ObjectHeader(
166             "1propB2Samp", ABCA::MetaData()));
167         awp = child->getProperties()->createArrayProperty("int",
168             ABCA::MetaData(), ABCA::DataType(Alembic::Util::kInt32POD, 1), 0);
169         awp->setSample(ABCA::ArraySample(&(vali.front()), i32d, dims));
170         awp->setSample(ABCA::ArraySample(&(valiB.front()), i32d, dims));
171 
172         // 2 objects with 4 samples, with repeats
173         child = archive->createChild(ABCA::ObjectHeader(
174             "1propA4Samp", ABCA::MetaData()));
175         awp = child->getProperties()->createArrayProperty("int",
176             ABCA::MetaData(), ABCA::DataType(Alembic::Util::kInt32POD, 1), 0);
177         awp->setSample(ABCA::ArraySample(&(vali.front()), i32d, dims));
178         awp->setSample(ABCA::ArraySample(&(vali.front()), i32d, dims));
179         awp->setSample(ABCA::ArraySample(&(valiB.front()), i32d, dims));
180         awp->setSample(ABCA::ArraySample(&(valiB.front()), i32d, dims));
181 
182         child = archive->createChild(ABCA::ObjectHeader(
183             "1propB4Samp", ABCA::MetaData()));
184         awp = child->getProperties()->createArrayProperty("int",
185             ABCA::MetaData(), ABCA::DataType(Alembic::Util::kInt32POD, 1), 0);
186         awp->setSample(ABCA::ArraySample(&(vali.front()), i32d, dims));
187         awp->setSample(ABCA::ArraySample(&(vali.front()), i32d, dims));
188         awp->setSample(ABCA::ArraySample(&(valiB.front()), i32d, dims));
189         awp->setSample(ABCA::ArraySample(&(valiB.front()), i32d, dims));
190 
191         // 2 objects with 1 samplem different dimensions
192         Alembic::Util::Dimensions dimsB;
193         dimsB.setRank(2);
194         dimsB[0] = 2;
195         dimsB[1] = 2;
196 
197         child = archive->createChild(ABCA::ObjectHeader(
198             "1propA1Dims", ABCA::MetaData()));
199         awp = child->getProperties()->createArrayProperty("int",
200             ABCA::MetaData(), ABCA::DataType(Alembic::Util::kInt32POD, 1), 0);
201         awp->setSample(ABCA::ArraySample(&(vali.front()), i32d, dimsB));
202 
203         child = archive->createChild(ABCA::ObjectHeader(
204             "1propB1Dims", ABCA::MetaData()));
205         awp = child->getProperties()->createArrayProperty("int",
206             ABCA::MetaData(), ABCA::DataType(Alembic::Util::kInt32POD, 1), 0);
207         awp->setSample(ABCA::ArraySample(&(vali.front()), i32d, dimsB));
208 
209         // 2 objects with with the same 2 properties with no samples
210         child = archive->createChild(ABCA::ObjectHeader(
211             "2propA", ABCA::MetaData()));
212         child->getProperties()->createArrayProperty("empty", ABCA::MetaData(),
213             ABCA::DataType(Alembic::Util::kInt32POD, 1), 0);
214         child->getProperties()->createArrayProperty("null",  ABCA::MetaData(),
215             ABCA::DataType(Alembic::Util::kInt32POD, 1), 0);
216 
217         child = archive->createChild(ABCA::ObjectHeader(
218             "2propB", ABCA::MetaData()));
219         child->getProperties()->createArrayProperty("empty",  ABCA::MetaData(),
220             ABCA::DataType(Alembic::Util::kInt32POD, 1), 0);
221         child->getProperties()->createArrayProperty("null",  ABCA::MetaData(),
222             ABCA::DataType(Alembic::Util::kInt32POD, 1), 0);
223 
224         // 2 objects with with the same 2 properties created in opposite order
225         child = archive->createChild(ABCA::ObjectHeader(
226             "2propASwap", ABCA::MetaData()));
227         child->getProperties()->createArrayProperty("null",  ABCA::MetaData(),
228             ABCA::DataType(Alembic::Util::kInt32POD, 1), 0);
229         child->getProperties()->createArrayProperty("empty",  ABCA::MetaData(),
230             ABCA::DataType(Alembic::Util::kInt32POD, 1), 0);
231 
232         child = archive->createChild(ABCA::ObjectHeader(
233             "2propBSwap", ABCA::MetaData()));
234         child->getProperties()->createArrayProperty("null",  ABCA::MetaData(),
235             ABCA::DataType(Alembic::Util::kInt32POD, 1), 0);
236         child->getProperties()->createArrayProperty("empty",  ABCA::MetaData(),
237             ABCA::DataType(Alembic::Util::kInt32POD, 1), 0);
238     }
239 
240     {
241         AO::ReadArchive r(1, iUseMMap);
242         ABCA::ArchiveReaderPtr a = r( archiveName );
243         ABCA::ObjectReaderPtr archive = a->getTop();
244 
245         TESTING_ASSERT(archive->getNumChildren() == 26);
246 
247         // every 2 hashes should be the same
248         for (size_t i = 0; i < archive->getNumChildren(); i += 2)
249         {
250             Alembic::Util::Digest dA, dB;
251             TESTING_ASSERT(archive->getChild(i)->getPropertiesHash(dA) &&
252                 archive->getChild(i+1)->getPropertiesHash(dB));
253             TESTING_ASSERT(dA == dB);
254         }
255 
256         // make sure that every 2 child objects have different properties hashes
257         for (size_t i = 0; i < archive->getNumChildren() / 2; ++i)
258         {
259             Alembic::Util::Digest dA;
260             archive->getChild(i*2)->getPropertiesHash(dA);
261             for (size_t j = i + 1; j < archive->getNumChildren() / 2; ++j)
262             {
263                 Alembic::Util::Digest dB;
264                 archive->getChild(j*2)->getPropertiesHash(dB);
265                 TESTING_ASSERT(dA != dB);
266             }
267         }
268     }
269 }
270 
testScalarPropHashes(bool iUseMMap)271 void testScalarPropHashes(bool iUseMMap)
272 {
273     std::string archiveName = "scalarHashTest.abc";
274     {
275         AO::WriteArchive w;
276         ABCA::ArchiveWriterPtr a = w(archiveName, ABCA::MetaData());
277         ABCA::ObjectWriterPtr archive = a->getTop();
278         ABCA::ObjectWriterPtr child;
279 
280         // add a time sampling for later use
281         std::vector < double > timeSamps(1,-4.0);
282         ABCA::TimeSamplingType tst(3.0);
283         ABCA::TimeSampling ts(tst, timeSamps);
284         a->addTimeSampling(ts);
285 
286         // 2 objects without any properties whatsoever
287         archive->createChild(ABCA::ObjectHeader("emptyA", ABCA::MetaData()));
288         archive->createChild(ABCA::ObjectHeader("emptyB", ABCA::MetaData()));
289 
290         // 2 objects with with the same property with no samples
291         child = archive->createChild(ABCA::ObjectHeader(
292             "1propA", ABCA::MetaData()));
293         child->getProperties()->createScalarProperty("empty",  ABCA::MetaData(),
294             ABCA::DataType(Alembic::Util::kInt32POD, 1), 0);
295 
296         child = archive->createChild(ABCA::ObjectHeader(
297             "1propB", ABCA::MetaData()));
298         child->getProperties()->createScalarProperty("empty",  ABCA::MetaData(),
299             ABCA::DataType(Alembic::Util::kInt32POD, 1), 0);
300 
301         // 2 objects with with the same property with a differnt name from above
302         child = archive->createChild(ABCA::ObjectHeader(
303             "1propAName", ABCA::MetaData()));
304         child->getProperties()->createScalarProperty("null",  ABCA::MetaData(),
305             ABCA::DataType(Alembic::Util::kInt32POD, 1), 0);
306 
307         child = archive->createChild(ABCA::ObjectHeader(
308             "1propBName", ABCA::MetaData()));
309         child->getProperties()->createScalarProperty("null",  ABCA::MetaData(),
310             ABCA::DataType(Alembic::Util::kInt32POD, 1), 0);
311 
312         // 2 objects with with the same property with a differnt MetaData
313         ABCA::MetaData m;
314         m.set("Bleep", "bloop");
315         child = archive->createChild(ABCA::ObjectHeader(
316             "1propAMeta", ABCA::MetaData()));
317         child->getProperties()->createScalarProperty("empty", m,
318             ABCA::DataType(Alembic::Util::kInt32POD, 1), 0);
319 
320         child = archive->createChild(ABCA::ObjectHeader(
321             "1propBMeta", ABCA::MetaData()));
322         child->getProperties()->createScalarProperty("empty", m,
323             ABCA::DataType(Alembic::Util::kInt32POD, 1), 0);
324 
325         // 2 objects with with the same property with a different POD
326         child = archive->createChild(ABCA::ObjectHeader(
327             "1propAPod", ABCA::MetaData()));
328         child->getProperties()->createScalarProperty("empty",  ABCA::MetaData(),
329             ABCA::DataType(Alembic::Util::kFloat32POD, 1), 0);
330 
331         child = archive->createChild(ABCA::ObjectHeader(
332             "1propBPod", ABCA::MetaData()));
333         child->getProperties()->createScalarProperty("empty",  ABCA::MetaData(),
334             ABCA::DataType(Alembic::Util::kFloat32POD, 1), 0);
335 
336         // 2 objects with with the same property with a different extent
337         child = archive->createChild(ABCA::ObjectHeader(
338             "1propAExtent", ABCA::MetaData()));
339         child->getProperties()->createScalarProperty("empty",  ABCA::MetaData(),
340             ABCA::DataType(Alembic::Util::kInt32POD, 2), 0);
341 
342         child = archive->createChild(ABCA::ObjectHeader(
343             "1propBExtent", ABCA::MetaData()));
344         child->getProperties()->createScalarProperty("empty",  ABCA::MetaData(),
345             ABCA::DataType(Alembic::Util::kInt32POD, 2), 0);
346 
347         // 2 objects with with the same property with a differnt time sampling
348         child = archive->createChild(ABCA::ObjectHeader(
349             "1propATS", ABCA::MetaData()));
350         child->getProperties()->createScalarProperty("empty",  ABCA::MetaData(),
351             ABCA::DataType(Alembic::Util::kInt32POD, 1), 1);
352 
353         child = archive->createChild(ABCA::ObjectHeader(
354             "1propBTS", ABCA::MetaData()));
355         child->getProperties()->createScalarProperty("empty",  ABCA::MetaData(),
356             ABCA::DataType(Alembic::Util::kInt32POD, 1), 1);
357 
358         // 2 objects with 1 sample
359         ABCA::ScalarPropertyWriterPtr swp;
360         Alembic::Util::int32_t vali = 0;
361         ABCA::DataType i32d(Alembic::Util::kInt32POD, 1);
362 
363         child = archive->createChild(ABCA::ObjectHeader(
364             "1propA1Samp", ABCA::MetaData()));
365         swp = child->getProperties()->createScalarProperty("int",
366             ABCA::MetaData(), ABCA::DataType(Alembic::Util::kInt32POD, 1), 0);
367         swp->setSample(&vali);
368 
369         child = archive->createChild(ABCA::ObjectHeader(
370             "1propB1Samp", ABCA::MetaData()));
371         swp = child->getProperties()->createScalarProperty("int",
372             ABCA::MetaData(), ABCA::DataType(Alembic::Util::kInt32POD, 1), 0);
373         swp->setSample(&vali);
374 
375         // 2 objects with 2 samples, no repeats
376         Alembic::Util::int32_t valiB = 1;
377 
378         child = archive->createChild(ABCA::ObjectHeader(
379             "1propA2Samp", ABCA::MetaData()));
380         swp = child->getProperties()->createScalarProperty("int",
381             ABCA::MetaData(), ABCA::DataType(Alembic::Util::kInt32POD, 1), 0);
382         swp->setSample(&vali);
383         swp->setSample(&valiB);
384 
385         child = archive->createChild(ABCA::ObjectHeader(
386             "1propB2Samp", ABCA::MetaData()));
387         swp = child->getProperties()->createScalarProperty("int",
388             ABCA::MetaData(), ABCA::DataType(Alembic::Util::kInt32POD, 1), 0);
389         swp->setSample(&vali);
390         swp->setSample(&valiB);
391 
392         // 2 objects with 4 samples, with repeats
393         child = archive->createChild(ABCA::ObjectHeader(
394             "1propA4Samp", ABCA::MetaData()));
395         swp = child->getProperties()->createScalarProperty("int",
396             ABCA::MetaData(), ABCA::DataType(Alembic::Util::kInt32POD, 1), 0);
397         swp->setSample(&vali);
398         swp->setSample(&vali);
399         swp->setSample(&valiB);
400         swp->setSample(&valiB);
401 
402         child = archive->createChild(ABCA::ObjectHeader(
403             "1propB4Samp", ABCA::MetaData()));
404         swp = child->getProperties()->createScalarProperty("int",
405             ABCA::MetaData(), ABCA::DataType(Alembic::Util::kInt32POD, 1), 0);
406         swp->setSample(&vali);
407         swp->setSample(&vali);
408         swp->setSample(&valiB);
409         swp->setSample(&valiB);
410 
411         // 2 objects with with the same 2 properties with no samples
412         child = archive->createChild(ABCA::ObjectHeader(
413             "2propA", ABCA::MetaData()));
414         child->getProperties()->createScalarProperty("empty", ABCA::MetaData(),
415             ABCA::DataType(Alembic::Util::kInt32POD, 1), 0);
416         child->getProperties()->createScalarProperty("null",  ABCA::MetaData(),
417             ABCA::DataType(Alembic::Util::kInt32POD, 1), 0);
418 
419         child = archive->createChild(ABCA::ObjectHeader(
420             "2propB", ABCA::MetaData()));
421         child->getProperties()->createScalarProperty("empty",  ABCA::MetaData(),
422             ABCA::DataType(Alembic::Util::kInt32POD, 1), 0);
423         child->getProperties()->createScalarProperty("null",  ABCA::MetaData(),
424             ABCA::DataType(Alembic::Util::kInt32POD, 1), 0);
425 
426         // 2 objects with with the same 2 properties created in opposite order
427         child = archive->createChild(ABCA::ObjectHeader(
428             "2propASwap", ABCA::MetaData()));
429         child->getProperties()->createScalarProperty("null",  ABCA::MetaData(),
430             ABCA::DataType(Alembic::Util::kInt32POD, 1), 0);
431         child->getProperties()->createScalarProperty("empty",  ABCA::MetaData(),
432             ABCA::DataType(Alembic::Util::kInt32POD, 1), 0);
433 
434         child = archive->createChild(ABCA::ObjectHeader(
435             "2propBSwap", ABCA::MetaData()));
436         child->getProperties()->createScalarProperty("null",  ABCA::MetaData(),
437             ABCA::DataType(Alembic::Util::kInt32POD, 1), 0);
438         child->getProperties()->createScalarProperty("empty",  ABCA::MetaData(),
439             ABCA::DataType(Alembic::Util::kInt32POD, 1), 0);
440     }
441 
442     {
443         AO::ReadArchive r(1, iUseMMap);
444         ABCA::ArchiveReaderPtr a = r( archiveName );
445         ABCA::ObjectReaderPtr archive = a->getTop();
446 
447         TESTING_ASSERT(archive->getNumChildren() == 24);
448 
449         // every 2 hashes should be the same
450         for (size_t i = 0; i < archive->getNumChildren(); i += 2)
451         {
452             Alembic::Util::Digest dA, dB;
453             TESTING_ASSERT(archive->getChild(i)->getPropertiesHash(dA) &&
454                 archive->getChild(i+1)->getPropertiesHash(dB));
455             TESTING_ASSERT(dA == dB);
456         }
457 
458         // make sure that every 2 child objects have different properties hashes
459         for (size_t i = 0; i < archive->getNumChildren() / 2; ++i)
460         {
461             Alembic::Util::Digest dA;
462             archive->getChild(i*2)->getPropertiesHash(dA);
463             for (size_t j = i + 1; j < archive->getNumChildren() / 2; ++j)
464             {
465                 Alembic::Util::Digest dB;
466                 archive->getChild(j*2)->getPropertiesHash(dB);
467                 TESTING_ASSERT(dA != dB);
468             }
469         }
470     }
471 }
472 
testCompoundPropHashes(bool iUseMMap)473 void testCompoundPropHashes(bool iUseMMap)
474 {
475     std::string archiveName = "compoundHashTest.abc";
476     {
477         AO::WriteArchive w;
478         ABCA::ArchiveWriterPtr a = w(archiveName, ABCA::MetaData());
479         ABCA::ObjectWriterPtr archive = a->getTop();
480         ABCA::ObjectWriterPtr child;
481 
482         // 2 objects without any properties whatsoever
483         archive->createChild(ABCA::ObjectHeader("emptyA", ABCA::MetaData()));
484         archive->createChild(ABCA::ObjectHeader("emptyB", ABCA::MetaData()));
485 
486         // 2 objects with with the same property with no samples
487         child = archive->createChild(ABCA::ObjectHeader(
488             "1propA", ABCA::MetaData()));
489         child->getProperties()->createCompoundProperty("empty",
490             ABCA::MetaData());
491 
492         child = archive->createChild(ABCA::ObjectHeader(
493             "1propB", ABCA::MetaData()));
494         child->getProperties()->createCompoundProperty("empty",
495             ABCA::MetaData());
496 
497         // 2 objects with with the same property with a differnt name from above
498         child = archive->createChild(ABCA::ObjectHeader(
499             "1propAName", ABCA::MetaData()));
500         child->getProperties()->createCompoundProperty("null",
501             ABCA::MetaData());
502 
503         child = archive->createChild(ABCA::ObjectHeader(
504             "1propBName", ABCA::MetaData()));
505         child->getProperties()->createCompoundProperty("null",
506             ABCA::MetaData());
507 
508         // 2 objects with with the same property with a different MetaData
509         ABCA::MetaData m;
510         m.set("Bleep", "bloop");
511         child = archive->createChild(ABCA::ObjectHeader(
512             "1propAMeta", ABCA::MetaData()));
513         child->getProperties()->createCompoundProperty("empty", m);
514 
515         child = archive->createChild(ABCA::ObjectHeader(
516             "1propBMeta", ABCA::MetaData()));
517         child->getProperties()->createCompoundProperty("empty", m);
518 
519         // 2 objects with compound that has a child compound
520         child = archive->createChild(ABCA::ObjectHeader(
521             "1propAChild", ABCA::MetaData()));
522         child->getProperties()->createCompoundProperty("withChild",
523             ABCA::MetaData())->createCompoundProperty("child",
524             ABCA::MetaData());
525 
526         child = archive->createChild(ABCA::ObjectHeader(
527             "1propBChild", ABCA::MetaData()));
528         child->getProperties()->createCompoundProperty("withChild",
529             ABCA::MetaData())->createCompoundProperty("child",
530             ABCA::MetaData());
531 
532         // 2 objects with compound that has various children
533         ABCA::CompoundPropertyWriterPtr childProp;
534         child = archive->createChild(ABCA::ObjectHeader(
535             "1propAProps", ABCA::MetaData()));
536         childProp = child->getProperties()->createCompoundProperty("child",
537             ABCA::MetaData());
538         childProp->createCompoundProperty("child", ABCA::MetaData());
539         childProp->createScalarProperty("empty", ABCA::MetaData(),
540             ABCA::DataType(Alembic::Util::kInt32POD, 1), 0);
541 
542         child = archive->createChild(ABCA::ObjectHeader(
543             "1propBProps", ABCA::MetaData()));
544         childProp = child->getProperties()->createCompoundProperty("child",
545             ABCA::MetaData());
546         childProp->createCompoundProperty("child", ABCA::MetaData());
547         childProp->createScalarProperty("empty", ABCA::MetaData(),
548             ABCA::DataType(Alembic::Util::kInt32POD, 1), 0);
549 
550         // 2 objects with compound that has hierarchy
551         ABCA::CompoundPropertyWriterPtr grandChildProp;
552         child = archive->createChild(ABCA::ObjectHeader(
553             "1propAHier", ABCA::MetaData()));
554         childProp = child->getProperties()->createCompoundProperty("child",
555             ABCA::MetaData());
556         grandChildProp = childProp->createCompoundProperty("child",
557             ABCA::MetaData());
558         childProp->createScalarProperty("empty", ABCA::MetaData(),
559             ABCA::DataType(Alembic::Util::kInt32POD, 1), 0);
560         grandChildProp->createScalarProperty("empty", ABCA::MetaData(),
561             ABCA::DataType(Alembic::Util::kInt32POD, 1), 0);
562         grandChildProp->createCompoundProperty("child", ABCA::MetaData());
563 
564         child = archive->createChild(ABCA::ObjectHeader(
565             "1propBHier", ABCA::MetaData()));
566         childProp = child->getProperties()->createCompoundProperty("child",
567             ABCA::MetaData());
568         grandChildProp = childProp->createCompoundProperty("child",
569             ABCA::MetaData());
570         childProp->createScalarProperty("empty", ABCA::MetaData(),
571             ABCA::DataType(Alembic::Util::kInt32POD, 1), 0);
572         grandChildProp->createScalarProperty("empty", ABCA::MetaData(),
573             ABCA::DataType(Alembic::Util::kInt32POD, 1), 0);
574         grandChildProp->createCompoundProperty("child", ABCA::MetaData());
575     }
576 
577     {
578         AO::ReadArchive r(1, iUseMMap);
579         ABCA::ArchiveReaderPtr a = r( archiveName );
580         ABCA::ObjectReaderPtr archive = a->getTop();
581 
582         TESTING_ASSERT(archive->getNumChildren() == 14);
583 
584         // every 2 hashes should be the same
585         for (size_t i = 0; i < archive->getNumChildren(); i += 2)
586         {
587             Alembic::Util::Digest dA, dB;
588             TESTING_ASSERT(archive->getChild(i)->getPropertiesHash(dA) &&
589                 archive->getChild(i+1)->getPropertiesHash(dB));
590             TESTING_ASSERT(dA == dB);
591         }
592 
593         // make sure that every 2 child objects have different properties hashes
594         for (size_t i = 0; i < archive->getNumChildren() / 2; ++i)
595         {
596             Alembic::Util::Digest dA;
597             archive->getChild(i*2)->getPropertiesHash(dA);
598             for (size_t j = i + 1; j < archive->getNumChildren() / 2; ++j)
599             {
600                 Alembic::Util::Digest dB;
601                 archive->getChild(j*2)->getPropertiesHash(dB);
602                 TESTING_ASSERT(dA != dB);
603             }
604         }
605     }
606 }
607 
testObjectHashes(bool iUseMMap)608 void testObjectHashes(bool iUseMMap)
609 {
610     std::string archiveName = "objectHashTest.abc";
611     {
612         AO::WriteArchive w;
613         ABCA::ArchiveWriterPtr a = w(archiveName, ABCA::MetaData());
614         ABCA::ObjectWriterPtr archive = a->getTop();
615         ABCA::ObjectWriterPtr child;
616 
617         // 2 objects without any children whatsoever
618         archive->createChild(ABCA::ObjectHeader("emptyA", ABCA::MetaData()));
619         archive->createChild(ABCA::ObjectHeader("emptyB", ABCA::MetaData()));
620 
621         // 2 objects with one child object
622         child = archive->createChild(ABCA::ObjectHeader("1ChildA",
623             ABCA::MetaData()));
624         child->createChild(ABCA::ObjectHeader("child", ABCA::MetaData()));
625 
626         child = archive->createChild(ABCA::ObjectHeader("1ChildB",
627             ABCA::MetaData()));
628         child->createChild(ABCA::ObjectHeader("child", ABCA::MetaData()));
629 
630         // 2 objects with one child object with a different name
631         child = archive->createChild(ABCA::ObjectHeader("1ChildAName",
632             ABCA::MetaData()));
633         child->createChild(ABCA::ObjectHeader("empty", ABCA::MetaData()));
634 
635         child = archive->createChild(ABCA::ObjectHeader("1ChildBName",
636             ABCA::MetaData()));
637         child->createChild(ABCA::ObjectHeader("empty", ABCA::MetaData()));
638 
639         // 2 objects with one child object with different MetaData
640         ABCA::MetaData m;
641         m.set("Bleep", "bloop");
642         child = archive->createChild(ABCA::ObjectHeader("1ChildAMeta",
643             ABCA::MetaData()));
644         child->createChild(ABCA::ObjectHeader("child", m));
645 
646         child = archive->createChild(ABCA::ObjectHeader("1ChildBMeta",
647             ABCA::MetaData()));
648         child->createChild(ABCA::ObjectHeader("child", m));
649 
650         // 2 objects with one child object additional prop
651         child = archive->createChild(ABCA::ObjectHeader("1ChildAProp",
652             ABCA::MetaData()));
653         child->createChild(ABCA::ObjectHeader("child", ABCA::MetaData())
654             )->getProperties()->createCompoundProperty("child",
655             ABCA::MetaData());
656 
657         child = archive->createChild(ABCA::ObjectHeader("1ChildBProp",
658             ABCA::MetaData()));
659         child->createChild(ABCA::ObjectHeader("child", ABCA::MetaData())
660             )->getProperties()->createCompoundProperty("child",
661             ABCA::MetaData());
662 
663         // 2 objects with one child object with additional grand child
664         child = archive->createChild(ABCA::ObjectHeader("1ChildAChild",
665             ABCA::MetaData()));
666         child->createChild(ABCA::ObjectHeader("child", ABCA::MetaData())
667             )->createChild(ABCA::ObjectHeader("grandchild", ABCA::MetaData()));
668 
669         child = archive->createChild(ABCA::ObjectHeader("1ChildBChild",
670             ABCA::MetaData()));
671         child->createChild(ABCA::ObjectHeader("child", ABCA::MetaData())
672             )->createChild(ABCA::ObjectHeader("grandchild", ABCA::MetaData()));
673 
674         // 2 objects with two children objects
675         child = archive->createChild(ABCA::ObjectHeader("2ChildA",
676             ABCA::MetaData()));
677         child->createChild(ABCA::ObjectHeader("childA", ABCA::MetaData()));
678         child->createChild(ABCA::ObjectHeader("childB", ABCA::MetaData()));
679 
680         child = archive->createChild(ABCA::ObjectHeader("2ChildB",
681             ABCA::MetaData()));
682         child->createChild(ABCA::ObjectHeader("childA", ABCA::MetaData()));
683         child->createChild(ABCA::ObjectHeader("childB", ABCA::MetaData()));
684 
685         // 2 objects with two children objects with swapped children
686         child = archive->createChild(ABCA::ObjectHeader("2ChildASwap",
687             ABCA::MetaData()));
688         child->createChild(ABCA::ObjectHeader("childB", ABCA::MetaData()));
689         child->createChild(ABCA::ObjectHeader("childA", ABCA::MetaData()));
690 
691         child = archive->createChild(ABCA::ObjectHeader("2ChildBSwap",
692             ABCA::MetaData()));
693         child->createChild(ABCA::ObjectHeader("childB", ABCA::MetaData()));
694         child->createChild(ABCA::ObjectHeader("childA", ABCA::MetaData()));
695     }
696 
697     {
698         AO::ReadArchive r(1, iUseMMap);
699         ABCA::ArchiveReaderPtr a = r( archiveName );
700         ABCA::ObjectReaderPtr archive = a->getTop();
701 
702         TESTING_ASSERT(archive->getNumChildren() == 16);
703 
704         // every 2 hashes should be the same
705         for (size_t i = 0; i < archive->getNumChildren(); i += 2)
706         {
707             Alembic::Util::Digest dA, dB;
708             TESTING_ASSERT(archive->getChild(i)->getChildrenHash(dA) &&
709                 archive->getChild(i+1)->getChildrenHash(dB));
710             TESTING_ASSERT(dA == dB);
711         }
712 
713         // make sure that every 2 child objects have different properties hashes
714         for (size_t i = 0; i < archive->getNumChildren() / 2; ++i)
715         {
716             Alembic::Util::Digest dA;
717             archive->getChild(i*2)->getChildrenHash(dA);
718             for (size_t j = i + 1; j < archive->getNumChildren() / 2; ++j)
719             {
720                 Alembic::Util::Digest dB;
721                 archive->getChild(j*2)->getChildrenHash(dB);
722                 TESTING_ASSERT(dA != dB);
723             }
724         }
725     }
726 }
727 
testStringHashes(bool iUseMMap)728 void testStringHashes(bool iUseMMap)
729 {
730     std::string archiveName = "stringsHashTest.abc";
731     {
732         AO::WriteArchive w;
733         ABCA::ArchiveWriterPtr a = w(archiveName, ABCA::MetaData());
734         ABCA::ObjectWriterPtr archive = a->getTop();
735         ABCA::CompoundPropertyWriterPtr props = archive->getProperties();
736 
737         ABCA::DataType wdtype(Alembic::Util::kWstringPOD, 1);
738         ABCA::ArrayPropertyWriterPtr wstrWrtPtr =
739             props->createArrayProperty("wstr", ABCA::MetaData(), wdtype, 0);
740 
741         std::vector < Alembic::Util::wstring > wvals(4);
742         wvals[0] = L"Mash potatoes ";
743         wvals[1] = L"with some delicious gravy.";
744         wvals[2] = L"";
745         wvals[3] = L"\uf8e4 \uf8e2 \uf8d3";
746 
747         for (size_t i = 0; i < wvals.size(); ++i)
748         {
749             Alembic::Util::Dimensions wdims(i);
750             wstrWrtPtr->setSample(
751                 ABCA::ArraySample(&(wvals.front()), wdtype, wdims));
752         }
753 
754         ABCA::DataType sdtype(Alembic::Util::kStringPOD, 1);
755         ABCA::ArrayPropertyWriterPtr strWrtPtr =
756             props->createArrayProperty("str", ABCA::MetaData(), sdtype, 0);
757 
758         std::vector < Alembic::Util::string > svals(4);
759         svals[0] = "Sunday, Monday";
760         svals[1] = "Tuesday, Wednesday, Thursday";
761         svals[2] = "";
762         svals[3] = "Some other days";
763 
764         for (size_t i = 0; i < svals.size(); ++i)
765         {
766             Alembic::Util::Dimensions sdims(i);
767             strWrtPtr->setSample(
768                 ABCA::ArraySample(&(svals.front()), sdtype, sdims));
769         }
770     }
771 
772     {
773         AO::ReadArchive r(1, iUseMMap);
774         ABCA::ArchiveReaderPtr a = r( archiveName );
775         ABCA::ObjectReaderPtr archive = a->getTop();
776         ABCA::CompoundPropertyReaderPtr parent = archive->getProperties();
777         ABCA::ArrayPropertyReaderPtr wap = parent->getArrayProperty("wstr");
778         std::vector< ABCA::ArraySampleKey > keys(wap->getNumSamples());
779         for (size_t i = 0; i < wap->getNumSamples(); ++i)
780         {
781             wap->getKey( (ABCA::index_t) i, keys[i] );
782         }
783 
784         for (size_t i = 0; i < keys.size(); ++i)
785         {
786             for (size_t j = i+1; j < keys.size(); ++j)
787             {
788                 TESTING_ASSERT( keys[i] != keys[j] );
789             }
790         }
791 
792         ABCA::ArrayPropertyReaderPtr sap = parent->getArrayProperty("str");
793         keys.resize(sap->getNumSamples());
794         for (size_t i = 0; i < sap->getNumSamples(); ++i)
795         {
796             sap->getKey( (ABCA::index_t) i, keys[i] );
797         }
798 
799         for (size_t i = 0; i < keys.size(); ++i)
800         {
801             for (size_t j = i+1; j < keys.size(); ++j)
802             {
803                 TESTING_ASSERT( keys[i] != keys[j] );
804             }
805         }
806     }
807 }
808 
runTests(bool iUseMMap)809 void runTests(bool iUseMMap)
810 {
811     testArrayPropHashes(iUseMMap);
812     testScalarPropHashes(iUseMMap);
813     testCompoundPropHashes(iUseMMap);
814     testObjectHashes(iUseMMap);
815     testStringHashes(iUseMMap);
816 }
817 
main(int argc,char * argv[])818 int main ( int argc, char *argv[] )
819 {
820     runTests(true);     // Use mmap
821     runTests(false);    // Use streams
822     return 0;
823 }
824