blob: 4476266ce76c1e3da295de7fed70352e5c50c36f [file] [log] [blame]
Michael Butler20f28a22019-04-26 17:46:08 -07001/*
Michael Butler0a1ad962019-04-30 13:51:24 -07002 * Copyright (C) 2019 The Android Open Source Project
Michael Butler20f28a22019-04-26 17:46:08 -07003 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#define LOG_TAG "neuralnetworks_hidl_hal_test"
18
19#include "VtsHalNeuralnetworks.h"
20
Slava Shklyaev73ee79d2019-05-14 14:15:14 +010021#include "1.2/Callbacks.h"
Michael Butler20f28a22019-04-26 17:46:08 -070022#include "ExecutionBurstController.h"
23#include "ExecutionBurstServer.h"
Xusong Wangbcaa7822019-08-23 16:10:54 -070024#include "GeneratedTestHarness.h"
Michael Butler20f28a22019-04-26 17:46:08 -070025#include "TestHarness.h"
Michael Butler20f28a22019-04-26 17:46:08 -070026
27#include <android-base/logging.h>
Michael Butler648ada52019-07-25 17:22:11 -070028#include <chrono>
Michael Butlerddb770f2019-05-02 18:16:13 -070029#include <cstring>
Michael Butler20f28a22019-04-26 17:46:08 -070030
Michael Butler62749b92019-08-26 23:55:47 -070031namespace android::hardware::neuralnetworks::V1_2::vts::functional {
Michael Butler20f28a22019-04-26 17:46:08 -070032
Michael Butler62749b92019-08-26 23:55:47 -070033using nn::ExecutionBurstController;
34using nn::RequestChannelSender;
35using nn::ResultChannelReceiver;
36using V1_0::ErrorStatus;
37using V1_0::Request;
38using ExecutionBurstCallback = ExecutionBurstController::ExecutionBurstCallback;
Michael Butler20f28a22019-04-26 17:46:08 -070039
Michael Butler68a6de72020-03-11 18:45:45 -070040using BurstExecutionMutation = std::function<void(std::vector<FmqRequestDatum>*)>;
41
Michael Butler0a1ad962019-04-30 13:51:24 -070042// This constant value represents the length of an FMQ that is large enough to
43// return a result from a burst execution for all of the generated test cases.
Michael Butler20f28a22019-04-26 17:46:08 -070044constexpr size_t kExecutionBurstChannelLength = 1024;
Michael Butler0a1ad962019-04-30 13:51:24 -070045
46// This constant value represents a length of an FMQ that is not large enough
47// to return a result from a burst execution for some of the generated test
48// cases.
Michael Butler20f28a22019-04-26 17:46:08 -070049constexpr size_t kExecutionBurstChannelSmallLength = 8;
50
51///////////////////////// UTILITY FUNCTIONS /////////////////////////
52
53static bool badTiming(Timing timing) {
54 return timing.timeOnDevice == UINT64_MAX && timing.timeInDriver == UINT64_MAX;
55}
56
57static void createBurst(const sp<IPreparedModel>& preparedModel, const sp<IBurstCallback>& callback,
58 std::unique_ptr<RequestChannelSender>* sender,
59 std::unique_ptr<ResultChannelReceiver>* receiver,
Michael Butler0a1ad962019-04-30 13:51:24 -070060 sp<IBurstContext>* context,
61 size_t resultChannelLength = kExecutionBurstChannelLength) {
Michael Butler20f28a22019-04-26 17:46:08 -070062 ASSERT_NE(nullptr, preparedModel.get());
63 ASSERT_NE(nullptr, sender);
64 ASSERT_NE(nullptr, receiver);
65 ASSERT_NE(nullptr, context);
66
67 // create FMQ objects
68 auto [fmqRequestChannel, fmqRequestDescriptor] =
Michael Butler648ada52019-07-25 17:22:11 -070069 RequestChannelSender::create(kExecutionBurstChannelLength);
Michael Butler20f28a22019-04-26 17:46:08 -070070 auto [fmqResultChannel, fmqResultDescriptor] =
Michael Butler648ada52019-07-25 17:22:11 -070071 ResultChannelReceiver::create(resultChannelLength, std::chrono::microseconds{0});
Michael Butler20f28a22019-04-26 17:46:08 -070072 ASSERT_NE(nullptr, fmqRequestChannel.get());
73 ASSERT_NE(nullptr, fmqResultChannel.get());
74 ASSERT_NE(nullptr, fmqRequestDescriptor);
75 ASSERT_NE(nullptr, fmqResultDescriptor);
76
77 // configure burst
78 ErrorStatus errorStatus;
79 sp<IBurstContext> burstContext;
80 const Return<void> ret = preparedModel->configureExecutionBurst(
81 callback, *fmqRequestDescriptor, *fmqResultDescriptor,
82 [&errorStatus, &burstContext](ErrorStatus status, const sp<IBurstContext>& context) {
83 errorStatus = status;
84 burstContext = context;
85 });
86 ASSERT_TRUE(ret.isOk());
87 ASSERT_EQ(ErrorStatus::NONE, errorStatus);
88 ASSERT_NE(nullptr, burstContext.get());
89
90 // return values
91 *sender = std::move(fmqRequestChannel);
92 *receiver = std::move(fmqResultChannel);
93 *context = burstContext;
94}
95
96static void createBurstWithResultChannelLength(
Michael Butler0a1ad962019-04-30 13:51:24 -070097 const sp<IPreparedModel>& preparedModel, size_t resultChannelLength,
98 std::shared_ptr<ExecutionBurstController>* controller) {
Michael Butler20f28a22019-04-26 17:46:08 -070099 ASSERT_NE(nullptr, preparedModel.get());
100 ASSERT_NE(nullptr, controller);
101
102 // create FMQ objects
Michael Butler0a1ad962019-04-30 13:51:24 -0700103 std::unique_ptr<RequestChannelSender> sender;
104 std::unique_ptr<ResultChannelReceiver> receiver;
Michael Butler20f28a22019-04-26 17:46:08 -0700105 sp<ExecutionBurstCallback> callback = new ExecutionBurstCallback();
Michael Butler0a1ad962019-04-30 13:51:24 -0700106 sp<IBurstContext> context;
107 ASSERT_NO_FATAL_FAILURE(createBurst(preparedModel, callback, &sender, &receiver, &context,
108 resultChannelLength));
109 ASSERT_NE(nullptr, sender.get());
110 ASSERT_NE(nullptr, receiver.get());
111 ASSERT_NE(nullptr, context.get());
Michael Butler20f28a22019-04-26 17:46:08 -0700112
113 // return values
Michael Butler0a1ad962019-04-30 13:51:24 -0700114 *controller = std::make_shared<ExecutionBurstController>(std::move(sender), std::move(receiver),
115 context, callback);
Michael Butler20f28a22019-04-26 17:46:08 -0700116}
117
118// Primary validation function. This function will take a valid serialized
119// request, apply a mutation to it to invalidate the serialized request, then
Michael Butler68a6de72020-03-11 18:45:45 -0700120// pass it to interface calls that use the serialized request.
Michael Butler20f28a22019-04-26 17:46:08 -0700121static void validate(RequestChannelSender* sender, ResultChannelReceiver* receiver,
Michael Butler68a6de72020-03-11 18:45:45 -0700122 const std::string& message,
123 const std::vector<FmqRequestDatum>& originalSerialized,
124 const BurstExecutionMutation& mutate) {
125 std::vector<FmqRequestDatum> serialized = originalSerialized;
126 mutate(&serialized);
Michael Butler20f28a22019-04-26 17:46:08 -0700127
128 // skip if packet is too large to send
129 if (serialized.size() > kExecutionBurstChannelLength) {
130 return;
131 }
132
133 SCOPED_TRACE(message);
134
135 // send invalid packet
Michael Butler0a1ad962019-04-30 13:51:24 -0700136 ASSERT_TRUE(sender->sendPacket(serialized));
Michael Butler20f28a22019-04-26 17:46:08 -0700137
138 // receive error
139 auto results = receiver->getBlocking();
140 ASSERT_TRUE(results.has_value());
141 const auto [status, outputShapes, timing] = std::move(*results);
142 EXPECT_NE(ErrorStatus::NONE, status);
143 EXPECT_EQ(0u, outputShapes.size());
144 EXPECT_TRUE(badTiming(timing));
145}
146
Michael Butler0a1ad962019-04-30 13:51:24 -0700147// For validation, valid packet entries are mutated to invalid packet entries,
148// or invalid packet entries are inserted into valid packets. This function
149// creates pre-set invalid packet entries for convenience.
150static std::vector<FmqRequestDatum> createBadRequestPacketEntries() {
Michael Butler20f28a22019-04-26 17:46:08 -0700151 const FmqRequestDatum::PacketInformation packetInformation = {
152 /*.packetSize=*/10, /*.numberOfInputOperands=*/10, /*.numberOfOutputOperands=*/10,
153 /*.numberOfPools=*/10};
154 const FmqRequestDatum::OperandInformation operandInformation = {
155 /*.hasNoValue=*/false, /*.location=*/{}, /*.numberOfDimensions=*/10};
156 const int32_t invalidPoolIdentifier = std::numeric_limits<int32_t>::max();
Michael Butler0a1ad962019-04-30 13:51:24 -0700157 std::vector<FmqRequestDatum> bad(7);
158 bad[0].packetInformation(packetInformation);
159 bad[1].inputOperandInformation(operandInformation);
160 bad[2].inputOperandDimensionValue(0);
161 bad[3].outputOperandInformation(operandInformation);
162 bad[4].outputOperandDimensionValue(0);
163 bad[5].poolIdentifier(invalidPoolIdentifier);
164 bad[6].measureTiming(MeasureTiming::YES);
165 return bad;
Michael Butler20f28a22019-04-26 17:46:08 -0700166}
167
Michael Butler0a1ad962019-04-30 13:51:24 -0700168// For validation, valid packet entries are mutated to invalid packet entries,
169// or invalid packet entries are inserted into valid packets. This function
170// retrieves pre-set invalid packet entries for convenience. This function
171// caches these data so they can be reused on subsequent validation checks.
172static const std::vector<FmqRequestDatum>& getBadRequestPacketEntries() {
173 static const std::vector<FmqRequestDatum> bad = createBadRequestPacketEntries();
174 return bad;
Michael Butler20f28a22019-04-26 17:46:08 -0700175}
176
177///////////////////////// REMOVE DATUM ////////////////////////////////////
178
179static void removeDatumTest(RequestChannelSender* sender, ResultChannelReceiver* receiver,
180 const std::vector<FmqRequestDatum>& serialized) {
181 for (size_t index = 0; index < serialized.size(); ++index) {
182 const std::string message = "removeDatum: removed datum at index " + std::to_string(index);
183 validate(sender, receiver, message, serialized,
184 [index](std::vector<FmqRequestDatum>* serialized) {
185 serialized->erase(serialized->begin() + index);
186 });
187 }
188}
189
190///////////////////////// ADD DATUM ////////////////////////////////////
191
192static void addDatumTest(RequestChannelSender* sender, ResultChannelReceiver* receiver,
193 const std::vector<FmqRequestDatum>& serialized) {
Michael Butler0a1ad962019-04-30 13:51:24 -0700194 const std::vector<FmqRequestDatum>& extra = getBadRequestPacketEntries();
Michael Butler20f28a22019-04-26 17:46:08 -0700195 for (size_t index = 0; index <= serialized.size(); ++index) {
196 for (size_t type = 0; type < extra.size(); ++type) {
197 const std::string message = "addDatum: added datum type " + std::to_string(type) +
198 " at index " + std::to_string(index);
199 validate(sender, receiver, message, serialized,
200 [index, type, &extra](std::vector<FmqRequestDatum>* serialized) {
201 serialized->insert(serialized->begin() + index, extra[type]);
202 });
203 }
204 }
205}
206
207///////////////////////// MUTATE DATUM ////////////////////////////////////
208
209static bool interestingCase(const FmqRequestDatum& lhs, const FmqRequestDatum& rhs) {
210 using Discriminator = FmqRequestDatum::hidl_discriminator;
211
212 const bool differentValues = (lhs != rhs);
Michael Butler0a1ad962019-04-30 13:51:24 -0700213 const bool sameDiscriminator = (lhs.getDiscriminator() == rhs.getDiscriminator());
Michael Butler20f28a22019-04-26 17:46:08 -0700214 const auto discriminator = rhs.getDiscriminator();
215 const bool isDimensionValue = (discriminator == Discriminator::inputOperandDimensionValue ||
216 discriminator == Discriminator::outputOperandDimensionValue);
217
Michael Butler0a1ad962019-04-30 13:51:24 -0700218 return differentValues && !(sameDiscriminator && isDimensionValue);
Michael Butler20f28a22019-04-26 17:46:08 -0700219}
220
221static void mutateDatumTest(RequestChannelSender* sender, ResultChannelReceiver* receiver,
222 const std::vector<FmqRequestDatum>& serialized) {
Michael Butler0a1ad962019-04-30 13:51:24 -0700223 const std::vector<FmqRequestDatum>& change = getBadRequestPacketEntries();
Michael Butler20f28a22019-04-26 17:46:08 -0700224 for (size_t index = 0; index < serialized.size(); ++index) {
225 for (size_t type = 0; type < change.size(); ++type) {
226 if (interestingCase(serialized[index], change[type])) {
227 const std::string message = "mutateDatum: changed datum at index " +
228 std::to_string(index) + " to datum type " +
229 std::to_string(type);
230 validate(sender, receiver, message, serialized,
231 [index, type, &change](std::vector<FmqRequestDatum>* serialized) {
232 (*serialized)[index] = change[type];
233 });
234 }
235 }
236 }
237}
238
239///////////////////////// BURST VALIATION TESTS ////////////////////////////////////
240
241static void validateBurstSerialization(const sp<IPreparedModel>& preparedModel,
Xusong Wang6d0270b2019-08-09 16:45:24 -0700242 const Request& request) {
Michael Butler20f28a22019-04-26 17:46:08 -0700243 // create burst
244 std::unique_ptr<RequestChannelSender> sender;
245 std::unique_ptr<ResultChannelReceiver> receiver;
246 sp<ExecutionBurstCallback> callback = new ExecutionBurstCallback();
247 sp<IBurstContext> context;
248 ASSERT_NO_FATAL_FAILURE(createBurst(preparedModel, callback, &sender, &receiver, &context));
249 ASSERT_NE(nullptr, sender.get());
250 ASSERT_NE(nullptr, receiver.get());
251 ASSERT_NE(nullptr, context.get());
252
Xusong Wang6d0270b2019-08-09 16:45:24 -0700253 // load memory into callback slots
254 std::vector<intptr_t> keys;
255 keys.reserve(request.pools.size());
256 std::transform(request.pools.begin(), request.pools.end(), std::back_inserter(keys),
257 [](const auto& pool) { return reinterpret_cast<intptr_t>(&pool); });
258 const std::vector<int32_t> slots = callback->getSlots(request.pools, keys);
Michael Butler20f28a22019-04-26 17:46:08 -0700259
Xusong Wang6d0270b2019-08-09 16:45:24 -0700260 // ensure slot std::numeric_limits<int32_t>::max() doesn't exist (for
261 // subsequent slot validation testing)
262 ASSERT_TRUE(std::all_of(slots.begin(), slots.end(), [](int32_t slot) {
263 return slot != std::numeric_limits<int32_t>::max();
264 }));
Michael Butler20f28a22019-04-26 17:46:08 -0700265
Xusong Wang6d0270b2019-08-09 16:45:24 -0700266 // serialize the request
Michael Butler07633282019-08-29 11:08:25 -0700267 const auto serialized = android::nn::serialize(request, MeasureTiming::YES, slots);
Michael Butler20f28a22019-04-26 17:46:08 -0700268
Xusong Wang6d0270b2019-08-09 16:45:24 -0700269 // validations
270 removeDatumTest(sender.get(), receiver.get(), serialized);
271 addDatumTest(sender.get(), receiver.get(), serialized);
272 mutateDatumTest(sender.get(), receiver.get(), serialized);
Michael Butler20f28a22019-04-26 17:46:08 -0700273}
274
Michael Butler0a1ad962019-04-30 13:51:24 -0700275// This test validates that when the Result message size exceeds length of the
276// result FMQ, the service instance gracefully fails and returns an error.
Michael Butler20f28a22019-04-26 17:46:08 -0700277static void validateBurstFmqLength(const sp<IPreparedModel>& preparedModel,
Xusong Wang6d0270b2019-08-09 16:45:24 -0700278 const Request& request) {
Michael Butler20f28a22019-04-26 17:46:08 -0700279 // create regular burst
280 std::shared_ptr<ExecutionBurstController> controllerRegular;
Michael Butler0a1ad962019-04-30 13:51:24 -0700281 ASSERT_NO_FATAL_FAILURE(createBurstWithResultChannelLength(
282 preparedModel, kExecutionBurstChannelLength, &controllerRegular));
Michael Butler20f28a22019-04-26 17:46:08 -0700283 ASSERT_NE(nullptr, controllerRegular.get());
284
285 // create burst with small output channel
286 std::shared_ptr<ExecutionBurstController> controllerSmall;
Michael Butler0a1ad962019-04-30 13:51:24 -0700287 ASSERT_NO_FATAL_FAILURE(createBurstWithResultChannelLength(
288 preparedModel, kExecutionBurstChannelSmallLength, &controllerSmall));
Michael Butler20f28a22019-04-26 17:46:08 -0700289 ASSERT_NE(nullptr, controllerSmall.get());
290
Xusong Wang6d0270b2019-08-09 16:45:24 -0700291 // load memory into callback slots
292 std::vector<intptr_t> keys(request.pools.size());
293 for (size_t i = 0; i < keys.size(); ++i) {
294 keys[i] = reinterpret_cast<intptr_t>(&request.pools[i]);
Michael Butler20f28a22019-04-26 17:46:08 -0700295 }
Xusong Wang6d0270b2019-08-09 16:45:24 -0700296
297 // collect serialized result by running regular burst
Michael Butler648ada52019-07-25 17:22:11 -0700298 const auto [nRegular, outputShapesRegular, timingRegular, fallbackRegular] =
Xusong Wang6d0270b2019-08-09 16:45:24 -0700299 controllerRegular->compute(request, MeasureTiming::NO, keys);
Michael Butlerd09c0ee2020-03-12 15:12:23 -0700300 const ErrorStatus statusRegular = nn::legacyConvertResultCodeToErrorStatus(nRegular);
Michael Butler648ada52019-07-25 17:22:11 -0700301 EXPECT_FALSE(fallbackRegular);
Xusong Wang6d0270b2019-08-09 16:45:24 -0700302
303 // skip test if regular burst output isn't useful for testing a failure
304 // caused by having too small of a length for the result FMQ
305 const std::vector<FmqResultDatum> serialized =
Michael Butler07633282019-08-29 11:08:25 -0700306 android::nn::serialize(statusRegular, outputShapesRegular, timingRegular);
Xusong Wang6d0270b2019-08-09 16:45:24 -0700307 if (statusRegular != ErrorStatus::NONE ||
308 serialized.size() <= kExecutionBurstChannelSmallLength) {
309 return;
310 }
311
312 // by this point, execution should fail because the result channel isn't
313 // large enough to return the serialized result
Michael Butler648ada52019-07-25 17:22:11 -0700314 const auto [nSmall, outputShapesSmall, timingSmall, fallbackSmall] =
Xusong Wang6d0270b2019-08-09 16:45:24 -0700315 controllerSmall->compute(request, MeasureTiming::NO, keys);
Michael Butlerd09c0ee2020-03-12 15:12:23 -0700316 const ErrorStatus statusSmall = nn::legacyConvertResultCodeToErrorStatus(nSmall);
Xusong Wang6d0270b2019-08-09 16:45:24 -0700317 EXPECT_NE(ErrorStatus::NONE, statusSmall);
318 EXPECT_EQ(0u, outputShapesSmall.size());
319 EXPECT_TRUE(badTiming(timingSmall));
Michael Butler648ada52019-07-25 17:22:11 -0700320 EXPECT_FALSE(fallbackSmall);
Michael Butler20f28a22019-04-26 17:46:08 -0700321}
322
Michael Butlerddb770f2019-05-02 18:16:13 -0700323static bool isSanitized(const FmqResultDatum& datum) {
324 using Discriminator = FmqResultDatum::hidl_discriminator;
325
326 // check to ensure the padding values in the returned
327 // FmqResultDatum::OperandInformation are initialized to 0
328 if (datum.getDiscriminator() == Discriminator::operandInformation) {
329 static_assert(
330 offsetof(FmqResultDatum::OperandInformation, isSufficient) == 0,
331 "unexpected value for offset of FmqResultDatum::OperandInformation::isSufficient");
332 static_assert(
333 sizeof(FmqResultDatum::OperandInformation::isSufficient) == 1,
334 "unexpected value for size of FmqResultDatum::OperandInformation::isSufficient");
335 static_assert(offsetof(FmqResultDatum::OperandInformation, numberOfDimensions) == 4,
336 "unexpected value for offset of "
337 "FmqResultDatum::OperandInformation::numberOfDimensions");
338 static_assert(sizeof(FmqResultDatum::OperandInformation::numberOfDimensions) == 4,
339 "unexpected value for size of "
340 "FmqResultDatum::OperandInformation::numberOfDimensions");
341 static_assert(sizeof(FmqResultDatum::OperandInformation) == 8,
342 "unexpected value for size of "
343 "FmqResultDatum::OperandInformation");
344
345 constexpr size_t paddingOffset =
346 offsetof(FmqResultDatum::OperandInformation, isSufficient) +
347 sizeof(FmqResultDatum::OperandInformation::isSufficient);
348 constexpr size_t paddingSize =
349 offsetof(FmqResultDatum::OperandInformation, numberOfDimensions) - paddingOffset;
350
351 FmqResultDatum::OperandInformation initialized{};
352 std::memset(&initialized, 0, sizeof(initialized));
353
354 const char* initializedPaddingStart =
355 reinterpret_cast<const char*>(&initialized) + paddingOffset;
356 const char* datumPaddingStart =
357 reinterpret_cast<const char*>(&datum.operandInformation()) + paddingOffset;
358
359 return std::memcmp(datumPaddingStart, initializedPaddingStart, paddingSize) == 0;
360 }
361
362 // there are no other padding initialization checks required, so return true
363 // for any sum-type that isn't FmqResultDatum::OperandInformation
364 return true;
365}
366
367static void validateBurstSanitized(const sp<IPreparedModel>& preparedModel,
Xusong Wang323ba2e2019-08-19 10:37:18 -0700368 const Request& request) {
Michael Butlerddb770f2019-05-02 18:16:13 -0700369 // create burst
370 std::unique_ptr<RequestChannelSender> sender;
371 std::unique_ptr<ResultChannelReceiver> receiver;
372 sp<ExecutionBurstCallback> callback = new ExecutionBurstCallback();
373 sp<IBurstContext> context;
374 ASSERT_NO_FATAL_FAILURE(createBurst(preparedModel, callback, &sender, &receiver, &context));
375 ASSERT_NE(nullptr, sender.get());
376 ASSERT_NE(nullptr, receiver.get());
377 ASSERT_NE(nullptr, context.get());
378
Xusong Wang323ba2e2019-08-19 10:37:18 -0700379 // load memory into callback slots
380 std::vector<intptr_t> keys;
381 keys.reserve(request.pools.size());
382 std::transform(request.pools.begin(), request.pools.end(), std::back_inserter(keys),
383 [](const auto& pool) { return reinterpret_cast<intptr_t>(&pool); });
384 const std::vector<int32_t> slots = callback->getSlots(request.pools, keys);
Michael Butlerddb770f2019-05-02 18:16:13 -0700385
Xusong Wang323ba2e2019-08-19 10:37:18 -0700386 // send valid request
387 ASSERT_TRUE(sender->send(request, MeasureTiming::YES, slots));
Michael Butlerddb770f2019-05-02 18:16:13 -0700388
Xusong Wang323ba2e2019-08-19 10:37:18 -0700389 // receive valid result
390 auto serialized = receiver->getPacketBlocking();
391 ASSERT_TRUE(serialized.has_value());
Michael Butlerddb770f2019-05-02 18:16:13 -0700392
Xusong Wang323ba2e2019-08-19 10:37:18 -0700393 // sanitize result
394 ASSERT_TRUE(std::all_of(serialized->begin(), serialized->end(), isSanitized))
395 << "The result serialized data is not properly sanitized";
Michael Butlerddb770f2019-05-02 18:16:13 -0700396}
397
Michael Butler20f28a22019-04-26 17:46:08 -0700398///////////////////////////// ENTRY POINT //////////////////////////////////
399
Michael Butler13b05162019-08-29 22:17:24 -0700400void validateBurst(const sp<IPreparedModel>& preparedModel, const Request& request) {
Xusong Wang6d0270b2019-08-09 16:45:24 -0700401 ASSERT_NO_FATAL_FAILURE(validateBurstSerialization(preparedModel, request));
402 ASSERT_NO_FATAL_FAILURE(validateBurstFmqLength(preparedModel, request));
Xusong Wang323ba2e2019-08-19 10:37:18 -0700403 ASSERT_NO_FATAL_FAILURE(validateBurstSanitized(preparedModel, request));
Michael Butler20f28a22019-04-26 17:46:08 -0700404}
405
Michael Butler62749b92019-08-26 23:55:47 -0700406} // namespace android::hardware::neuralnetworks::V1_2::vts::functional