@@ -56,20 +56,39 @@ class ManagedBinaryFile {
5656};
5757
5858std::vector<uint8_t > generateRandomImage () {
59- std::mt19937 Rng (42 );
60- std::uniform_int_distribution<uint64_t > SizeDist (0 , 256 );
61- std::uniform_int_distribution<uint16_t > KindDist (0 );
62- std::uniform_int_distribution<uint16_t > BinaryDist (
59+ static std::mt19937 Rng (42 );
60+ static std::uniform_int_distribution<uint64_t > SizeDist (0 , 256 );
61+ static std::uniform_int_distribution<uint16_t > BinaryDist (
6362 std::numeric_limits<uint8_t >::min (), std::numeric_limits<uint8_t >::max ());
6463 std::vector<uint8_t > Image (SizeDist (Rng));
6564 std::generate (Image.begin (), Image.end (), [&]() { return BinaryDist (Rng); });
6665 return Image;
6766}
6867
69- } // namespace
68+ std::vector<std::vector<uint8_t >> generateUniqueRandomImages (size_t NumImages) {
69+ std::vector<std::vector<uint8_t >> Images;
70+ Images.reserve (NumImages);
71+ Images.emplace_back (generateRandomImage ());
72+ for (size_t I = 1 ; I < NumImages; ++I) {
73+ std::vector<uint8_t > GenImage;
74+ auto CheckImageExist = [&](const std::vector<uint8_t > &Image) {
75+ return GenImage.size () == Image.size () &&
76+ std::memcmp (GenImage.data (), Image.data (), GenImage.size ()) == 0 ;
77+ };
78+ // Generate images until we get a unique one.
79+ do {
80+ GenImage = generateRandomImage ();
81+ } while (std::any_of (Images.begin (), Images.end (), CheckImageExist));
82+ Images.emplace_back (std::move (GenImage));
83+ }
84+ return Images;
85+ }
7086
71- TEST (SYCLBINTest, checkSYCLBINBinaryBasicIRModule) {
87+ template <size_t NumIRModules, size_t NumNativeDeviceCodeImages>
88+ void CommonCheck () {
89+ constexpr size_t NumImages = NumIRModules + NumNativeDeviceCodeImages;
7290 constexpr SYCLBIN::BundleState State = SYCLBIN::BundleState::Input;
91+ static constexpr char Arch[] = " some-arch" ;
7392
7493 // Create unique temporary directory for these tests
7594 SmallString<128 > TestDirectory;
@@ -78,21 +97,32 @@ TEST(SYCLBINTest, checkSYCLBINBinaryBasicIRModule) {
7897 fs::createUniqueDirectory (" SYCLBINTest-test" , TestDirectory));
7998 }
8099
81- // Create a random file to be used in the SYCLBIN.
82- SmallString<128 > File1 (TestDirectory);
83- File1.append (" /image_file1" );
84- std::vector<uint8_t > Image = generateRandomImage ();
85- Expected<ManagedBinaryFile> ManagedModuleFileOrError =
86- ManagedBinaryFile::create (File1, Image);
87- ASSERT_THAT_EXPECTED (ManagedModuleFileOrError, Succeeded ());
88- ManagedBinaryFile ManagedModuleFile = std::move (*ManagedModuleFileOrError);
89-
90- // Create IR module.
91- std::vector<module_split::SplitModule> SplitModules{module_split::SplitModule{
92- File1.c_str (), util::PropertySetRegistry{}, " " }};
93- SmallVector<SYCLBIN::SYCLBINModuleDesc> MDs{
94- SYCLBIN::SYCLBINModuleDesc{" " , std::move (SplitModules)}};
95- SYCLBIN::SYCLBINDesc Desc{SYCLBIN::BundleState::Input, MDs};
100+ // Create random files to be used in the SYCLBIN. If the same image is
101+ // generated, retry until they are unique.
102+ std::vector<std::vector<uint8_t >> Images =
103+ generateUniqueRandomImages (NumImages);
104+
105+ std::vector<ManagedBinaryFile> ManagedModuleFiles;
106+ SmallVector<SYCLBIN::SYCLBINModuleDesc> MDs;
107+ ManagedModuleFiles.reserve (NumImages);
108+ MDs.reserve (NumImages);
109+ for (size_t I = 0 ; I < NumImages; ++I) {
110+ SmallString<128 > File (TestDirectory);
111+ llvm::sys::path::append (File, " image_file" + std::to_string (I));
112+ Expected<ManagedBinaryFile> ManagedModuleFileOrError =
113+ ManagedBinaryFile::create (File, Images[I]);
114+ ASSERT_THAT_EXPECTED (ManagedModuleFileOrError, Succeeded ());
115+ ManagedModuleFiles.emplace_back (std::move (*ManagedModuleFileOrError));
116+ std::vector<module_split::SplitModule> SplitModules{
117+ module_split::SplitModule{File.c_str (), util::PropertySetRegistry{},
118+ " " }};
119+ const char *ArchStr = I < NumIRModules ? " " : Arch;
120+ MDs.emplace_back (
121+ SYCLBIN::SYCLBINModuleDesc{ArchStr, std::move (SplitModules)});
122+ }
123+
124+ // Create IR modules.
125+ SYCLBIN::SYCLBINDesc Desc{State, MDs};
96126 size_t SYCLBINByteSize = 0 ;
97127 if (Error E = Desc.getSYCLBINByteSite ().moveInto (SYCLBINByteSize))
98128 FAIL () << " Failed to get SYCLBIN byte size." ;
@@ -133,146 +163,106 @@ TEST(SYCLBINTest, checkSYCLBINBinaryBasicIRModule) {
133163 ASSERT_EQ (GlobalMetadataState.getType (), PropertyValue::Type::UINT32);
134164 EXPECT_EQ (GlobalMetadataState.asUint32 (), static_cast <uint32_t >(State));
135165
136- ASSERT_EQ (SYCLBINObj->AbstractModules .size (), size_t {1 });
137- const SYCLBIN::AbstractModule &AM = SYCLBINObj->AbstractModules [0 ];
138-
139- // This metadata should be the same as in the corresponding split module, so
140- // testing should be expanded to ensure preservation.
141- ASSERT_NE (AM.Metadata .get (), nullptr );
142- EXPECT_TRUE (AM.Metadata ->getPropSets ().empty ());
143-
144- // There was no arch string, so there should be no native device code images.
145- EXPECT_TRUE (AM.NativeDeviceCodeImages .empty ());
146-
147- // There was a single module with no arch string, so we should have an IR
148- // module.
149- ASSERT_EQ (AM.IRModules .size (), size_t {1 });
150- const SYCLBIN::IRModule &IRM = AM.IRModules [0 ];
151-
152- ASSERT_NE (IRM.Metadata .get (), nullptr );
153- SmallString<16 > IRMMetadataKey{
154- PropertySetRegistry::SYCLBIN_IR_MODULE_METADATA};
155- const auto &IRMMetadataIt = IRM.Metadata ->getPropSets ().find (IRMMetadataKey);
156- ASSERT_NE (IRMMetadataIt, IRM.Metadata ->end ());
157- const PropertySet &IRMMetadata = IRMMetadataIt->second ;
158- EXPECT_EQ (IRMMetadata.size (), size_t {1 });
159-
160- // The type is currently locked to SPIR-V. This will change in the future.
161- SmallString<16 > IRMMetadataTypeKey{" type" };
162- const auto &IRMMetadataTypeIt = IRMMetadata.find (IRMMetadataTypeKey);
163- ASSERT_NE (IRMMetadataTypeIt, IRMMetadata.end ());
164- const PropertyValue &IRMMetadataType = IRMMetadataTypeIt->second ;
165- ASSERT_EQ (IRMMetadataType.getType (), PropertyValue::Type::UINT32);
166- EXPECT_EQ (IRMMetadataType.asUint32 (), uint32_t {0 });
167-
168- // Check that the image is the same.
169- ASSERT_EQ (Image.size (), IRM.RawIRBytes .size ());
170- EXPECT_EQ (std::memcmp (Image.data (), IRM.RawIRBytes .data (), Image.size ()), 0 );
171- }
172-
173- TEST (SYCLBINTest, checkSYCLBINBinaryBasicNativeDeviceCodeImage) {
174- constexpr SYCLBIN::BundleState State = SYCLBIN::BundleState::Input;
175- static constexpr char Arch[] = " some-arch" ;
176-
177- // Create unique temporary directory for these tests
178- SmallString<128 > TestDirectory;
179- {
180- ASSERT_NO_ERROR (
181- fs::createUniqueDirectory (" SYCLBINTest-test" , TestDirectory));
166+ // Currently we have an abstract module per image.
167+ ASSERT_EQ (SYCLBINObj->AbstractModules .size (), size_t {NumImages});
168+
169+ std::vector<decltype (Images)::const_iterator> ImageIts;
170+ ImageIts.reserve (NumImages);
171+ size_t ObservedIRModules = 0 , ObservedNativeDeviceCodeImages = 0 ;
172+ for (size_t I = 0 ; I < NumImages; ++I) {
173+ const SYCLBIN::AbstractModule &AM = SYCLBINObj->AbstractModules [I];
174+
175+ // This metadata should be the same as in the corresponding split module, so
176+ // testing should be expanded to ensure preservation.
177+ ASSERT_NE (AM.Metadata .get (), nullptr );
178+ EXPECT_TRUE (AM.Metadata ->getPropSets ().empty ());
179+
180+ ObservedIRModules += AM.IRModules .size ();
181+ for (size_t J = 0 ; J < AM.IRModules .size (); ++J) {
182+ const SYCLBIN::IRModule &IRM = AM.IRModules [J];
183+ ASSERT_NE (IRM.Metadata .get (), nullptr );
184+ SmallString<16 > IRMMetadataKey{
185+ PropertySetRegistry::SYCLBIN_IR_MODULE_METADATA};
186+ const auto &IRMMetadataIt =
187+ IRM.Metadata ->getPropSets ().find (IRMMetadataKey);
188+ ASSERT_NE (IRMMetadataIt, IRM.Metadata ->end ());
189+ const PropertySet &IRMMetadata = IRMMetadataIt->second ;
190+ EXPECT_EQ (IRMMetadata.size (), size_t {1 });
191+
192+ // The type is currently locked to SPIR-V. This will change in the future.
193+ SmallString<16 > IRMMetadataTypeKey{" type" };
194+ const auto &IRMMetadataTypeIt = IRMMetadata.find (IRMMetadataTypeKey);
195+ ASSERT_NE (IRMMetadataTypeIt, IRMMetadata.end ());
196+ const PropertyValue &IRMMetadataType = IRMMetadataTypeIt->second ;
197+ ASSERT_EQ (IRMMetadataType.getType (), PropertyValue::Type::UINT32);
198+ EXPECT_EQ (IRMMetadataType.asUint32 (), uint32_t {0 });
199+
200+ // Find the image that matches.
201+ std::vector<uint8_t > IRImage{IRM.RawIRBytes .begin (),
202+ IRM.RawIRBytes .end ()};
203+ auto ImageMatchIt = std::find (Images.begin (), Images.end (), IRImage);
204+ ASSERT_NE (ImageMatchIt, Images.end ());
205+ ImageIts.push_back (ImageMatchIt);
206+ }
207+
208+ ObservedNativeDeviceCodeImages += AM.NativeDeviceCodeImages .size ();
209+ for (size_t J = 0 ; J < AM.NativeDeviceCodeImages .size (); ++J) {
210+ const SYCLBIN::NativeDeviceCodeImage &NDCI = AM.NativeDeviceCodeImages [J];
211+
212+ ASSERT_NE (NDCI.Metadata .get (), nullptr );
213+ SmallString<16 > NDCIMetadataKey{
214+ PropertySetRegistry::SYCLBIN_NATIVE_DEVICE_CODE_IMAGE_METADATA};
215+ const auto &NDCIMetadataIt =
216+ NDCI.Metadata ->getPropSets ().find (NDCIMetadataKey);
217+ ASSERT_NE (NDCIMetadataIt, NDCI.Metadata ->end ());
218+ const PropertySet &NDCIMetadata = NDCIMetadataIt->second ;
219+ ASSERT_EQ (NDCIMetadata.size (), size_t {1 });
220+
221+ // Make sure the arch string is preserved.
222+ SmallString<16 > NDCIMetadataArchKey{" arch" };
223+ const auto &NDCIMetadataArchIt = NDCIMetadata.find (NDCIMetadataArchKey);
224+ ASSERT_NE (NDCIMetadataArchIt, NDCIMetadata.end ());
225+ const PropertyValue &NDCIMetadataArch = NDCIMetadataArchIt->second ;
226+ ASSERT_EQ (NDCIMetadataArch.getType (), PropertyValue::Type::BYTE_ARRAY);
227+ ASSERT_EQ (NDCIMetadataArch.getByteArraySize (), strlen (Arch));
228+ EXPECT_EQ (std::memcmp (NDCIMetadataArch.asByteArray (), Arch, strlen (Arch)),
229+ 0 );
230+
231+ // Find the image that matches.
232+ std::vector<uint8_t > RawDeviceCodeImage{
233+ NDCI.RawDeviceCodeImageBytes .begin (),
234+ NDCI.RawDeviceCodeImageBytes .end ()};
235+ auto ImageMatchIt =
236+ std::find (Images.begin (), Images.end (), RawDeviceCodeImage);
237+ ASSERT_NE (ImageMatchIt, Images.end ());
238+ ImageIts.push_back (ImageMatchIt);
239+ }
182240 }
241+ ASSERT_EQ (NumIRModules, ObservedIRModules);
242+ ASSERT_EQ (NumNativeDeviceCodeImages, ObservedNativeDeviceCodeImages);
243+ // The images may not appear in the same order they were written. They
244+ // shouldn't be the same however.
245+ ASSERT_TRUE (std::unique (ImageIts.begin (), ImageIts.end ()) == ImageIts.end ());
246+ }
183247
184- // Create a random file to be used in the SYCLBIN.
185- SmallString<128 > File1 (TestDirectory);
186- File1.append (" /image_file1" );
187- std::vector<uint8_t > Image = generateRandomImage ();
188- Expected<ManagedBinaryFile> ManagedModuleFileOrError =
189- ManagedBinaryFile::create (File1, Image);
190- ASSERT_THAT_EXPECTED (ManagedModuleFileOrError, Succeeded ());
191- ManagedBinaryFile ManagedModuleFile = std::move (*ManagedModuleFileOrError);
192-
193- // Create IR module.
194- std::vector<module_split::SplitModule> SplitModules{module_split::SplitModule{
195- File1.c_str (), util::PropertySetRegistry{}, " " }};
196- SmallVector<SYCLBIN::SYCLBINModuleDesc> MDs{
197- SYCLBIN::SYCLBINModuleDesc{Arch, std::move (SplitModules)}};
198- SYCLBIN::SYCLBINDesc Desc{SYCLBIN::BundleState::Input, MDs};
199- size_t SYCLBINByteSize = 0 ;
200- if (Error E = Desc.getSYCLBINByteSite ().moveInto (SYCLBINByteSize))
201- FAIL () << " Failed to get SYCLBIN byte size." ;
202-
203- // Serialize the SYCLBIN.
204- SmallString<0 > SYCLBINImage;
205- SYCLBINImage.reserve (SYCLBINByteSize);
206- raw_svector_ostream SYCLBINImageOS{SYCLBINImage};
207- if (Error E = SYCLBIN::write (Desc, SYCLBINImageOS))
208- FAIL () << " Failed to write SYCLBIN." ;
248+ } // namespace
209249
210- // Deserialize the SYCLBIN.
211- std::unique_ptr<MemoryBuffer> SYCBINDataBuffer =
212- MemoryBuffer::getMemBuffer (SYCLBINImage, /* BufferName=*/ " " ,
213- /* RequiresNullTerminator=*/ false );
214- Expected<std::unique_ptr<SYCLBIN>> SYCLBINObjOrError =
215- SYCLBIN::read (*SYCBINDataBuffer);
216- ASSERT_THAT_EXPECTED (SYCLBINObjOrError, Succeeded ());
217- SYCLBIN *SYCLBINObj = SYCLBINObjOrError->get ();
218- ASSERT_NE (SYCLBINObj, nullptr );
250+ TEST (SYCLBINTest, checkSYCLBINBinaryBasicIRModule) {
251+ CommonCheck</* NumIRModules=*/ 1 , /* NumNativeDeviceCodeImages=*/ 0 >();
252+ }
219253
220- EXPECT_EQ (SYCLBINObj->Version , SYCLBIN::CurrentVersion);
254+ TEST (SYCLBINTest, checkSYCLBINBinaryDoubleBasicIRModules) {
255+ CommonCheck</* NumIRModules=*/ 2 , /* NumNativeDeviceCodeImages=*/ 0 >();
256+ }
221257
222- ASSERT_NE (SYCLBINObj->GlobalMetadata .get (), nullptr );
223- SmallString<16 > GlobalMetadataKey{
224- PropertySetRegistry::SYCLBIN_GLOBAL_METADATA};
225- const auto &GlobalMetadataIt =
226- SYCLBINObj->GlobalMetadata ->getPropSets ().find (GlobalMetadataKey);
227- ASSERT_NE (GlobalMetadataIt, SYCLBINObj->GlobalMetadata ->end ());
228- const PropertySet &GlobalMetadata = GlobalMetadataIt->second ;
229- EXPECT_EQ (GlobalMetadata.size (), size_t {1 });
258+ TEST (SYCLBINTest, checkSYCLBINBinaryBasicNativeDeviceCodeImage) {
259+ CommonCheck</* NumIRModules=*/ 0 , /* NumNativeDeviceCodeImages=*/ 1 >();
260+ }
230261
231- SmallString<16 > GlobalMetadataStateKey{" state" };
232- const auto &GlobalMetadataStateIt =
233- GlobalMetadata.find (GlobalMetadataStateKey);
234- ASSERT_NE (GlobalMetadataStateIt, GlobalMetadata.end ());
235- const PropertyValue &GlobalMetadataState = GlobalMetadataStateIt->second ;
236- ASSERT_EQ (GlobalMetadataState.getType (), PropertyValue::Type::UINT32);
237- EXPECT_EQ (GlobalMetadataState.asUint32 (), static_cast <uint32_t >(State));
262+ TEST (SYCLBINTest, checkSYCLBINBinaryDoubleBasicNativeDeviceCodeImages) {
263+ CommonCheck</* NumIRModules=*/ 0 , /* NumNativeDeviceCodeImages=*/ 2 >();
264+ }
238265
239- ASSERT_EQ (SYCLBINObj->AbstractModules .size (), size_t {1 });
240- const SYCLBIN::AbstractModule &AM = SYCLBINObj->AbstractModules [0 ];
241-
242- // This metadata should be the same as in the corresponding split module, so
243- // testing should be expanded to ensure preservation.
244- ASSERT_NE (AM.Metadata .get (), nullptr );
245- EXPECT_TRUE (AM.Metadata ->getPropSets ().empty ());
246-
247- // There was a single module with an arch string, so we should not have an IR
248- // module.
249- EXPECT_TRUE (AM.IRModules .empty ());
250-
251- // There was an arch string, so there should be a native device code images.
252- ASSERT_EQ (AM.NativeDeviceCodeImages .size (), size_t {1 });
253- const SYCLBIN::NativeDeviceCodeImage &NDCI = AM.NativeDeviceCodeImages [0 ];
254-
255- ASSERT_NE (NDCI.Metadata .get (), nullptr );
256- SmallString<16 > NDCIMetadataKey{
257- PropertySetRegistry::SYCLBIN_NATIVE_DEVICE_CODE_IMAGE_METADATA};
258- const auto &NDCIMetadataIt =
259- NDCI.Metadata ->getPropSets ().find (NDCIMetadataKey);
260- ASSERT_NE (NDCIMetadataIt, NDCI.Metadata ->end ());
261- const PropertySet &NDCIMetadata = NDCIMetadataIt->second ;
262- ASSERT_EQ (NDCIMetadata.size (), size_t {1 });
263-
264- // Make sure the arch string is preserved.
265- SmallString<16 > NDCIMetadataArchKey{" arch" };
266- const auto &NDCIMetadataArchIt = NDCIMetadata.find (NDCIMetadataArchKey);
267- ASSERT_NE (NDCIMetadataArchIt, NDCIMetadata.end ());
268- const PropertyValue &NDCIMetadataArch = NDCIMetadataArchIt->second ;
269- ASSERT_EQ (NDCIMetadataArch.getType (), PropertyValue::Type::BYTE_ARRAY);
270- ASSERT_EQ (NDCIMetadataArch.getByteArraySize (), strlen (Arch));
271- EXPECT_EQ (std::memcmp (NDCIMetadataArch.asByteArray (), Arch, strlen (Arch)), 0 );
272-
273- // Check that the image is the same.
274- ASSERT_EQ (Image.size (), NDCI.RawDeviceCodeImageBytes .size ());
275- EXPECT_EQ (std::memcmp (Image.data (), NDCI.RawDeviceCodeImageBytes .data (),
276- Image.size ()),
277- 0 );
266+ TEST (SYCLBINTest, checkSYCLBINBinaryMixBasicImages) {
267+ CommonCheck</* NumIRModules=*/ 1 , /* NumNativeDeviceCodeImages=*/ 1 >();
278268}
0 commit comments