1 /* 2 * Copyright (C) 2019 The Android Open Source Project 3 * 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 #ifndef ANDROID_FRAMEWORK_ML_NN_RUNTIME_TEST_FUZZING_OPERATION_MANAGER_H 18 #define ANDROID_FRAMEWORK_ML_NN_RUNTIME_TEST_FUZZING_OPERATION_MANAGER_H 19 20 #include <functional> 21 #include <map> 22 #include <string> 23 #include <vector> 24 25 #include "TestNeuralNetworksWrapper.h" 26 #include "fuzzing/RandomGraphGenerator.h" 27 #include "fuzzing/RandomVariable.h" 28 29 namespace android { 30 namespace nn { 31 namespace fuzzing_test { 32 33 using test_wrapper::Type; 34 35 struct OperandSignature { 36 // Possible values are [INPUT | CONST | OUTPUT]. 37 // If CONST, the generator will avoid feeding the operand with another operation’s output. 38 RandomOperandType type; 39 40 // The operand constructor is invoked before the operation constructor. This is for 41 // setting the data type, quantization parameters, or optionally the scalar value. 42 std::function<void(Type, uint32_t, RandomOperand*)> constructor = nullptr; 43 44 // The operand finalizer is invoked after the graph structure is frozen but before the operation 45 // finalizer. This is for generating the buffer values for the operand. 46 std::function<void(RandomOperand*)> finalizer = nullptr; 47 }; 48 49 enum class HalVersion : int32_t { V1_0 = 0, V1_1 = 1, V1_2 = 2 }; 50 51 // A filter applied to OperationSignatures. An OperationSignature is filtered out if the opType, all 52 // of supportedDataTypes, all of supportedRanks, or the version does not match with any entry in the 53 // corresponding vector in the filter. Use empty vector in the filter for "no filter". 54 // 55 // E.g. 56 // - To get all 1.0 ADD operation signatures 57 // {.opcodes = {ANEURALNETWORKS_ADD}, .versions = {HalVersion::V1_0}} 58 // 59 // - To get all 1.0 and 1.1 operations with rank 2 or 4 60 // {.ranks = {2, 4}, .versions = {HalVersion::V1_0, HalVersion::V1_1}} 61 // 62 struct OperationFilter { 63 std::vector<ANeuralNetworksOperationType> opcodes; 64 std::vector<Type> dataTypes; 65 std::vector<uint32_t> ranks; 66 std::vector<HalVersion> versions; 67 }; 68 69 struct OperationSignature { 70 // Defines the basic metadata of an operation filterable by OperationFilter. 71 // Upon generation, the random graph generator will randomly choose a supported data type and 72 // rank, and pass the information to the constructors. 73 ANeuralNetworksOperationType opType; 74 std::vector<Type> supportedDataTypes; 75 std::vector<uint32_t> supportedRanks; 76 HalVersion version; 77 78 // OperandSignatures for inputs and outputs. 79 std::vector<OperandSignature> inputs; 80 std::vector<OperandSignature> outputs; 81 82 // The operation constructor is invoked after the inputs and outputs constructor. This is for 83 // setting the dimension relationship of random operands, and/or generating parameter values at 84 // the operation level, e.g. a parameter depends on or affects another operand in the same 85 // operation. 86 std::function<void(Type, uint32_t, RandomOperation*)> constructor = nullptr; 87 88 // The operation finalizer is invoked after the graph structure is frozen and inputs and outputs 89 // constructors are invoked. This is for generating operand buffers at the operation level, e.g. 90 // an operand buffer that depends on another operand in the same operation. 91 std::function<void(RandomOperation*)> finalizer = nullptr; 92 93 // Check if the OperationSignature matches with the filter. Shrink supported* if needed. 94 bool matchFilter(const OperationFilter& filter); 95 }; 96 97 // A manager manages all available OperationSignatures. 98 class OperationManager { 99 public: 100 // Returns the singleton manager. 101 static OperationManager* get(); 102 103 // Add the signature to the managed mOperationSignatures if matches with mFilter. 104 void addSignature(const std::string& name, const OperationSignature& signature); 105 106 // Reinitialize mFilteredSignatures by applying a filter to all of the operation signatures in 107 // mOperationSignatures. 108 void applyFilter(const OperationFilter& filter); 109 110 // Randomly returns a valid OperationSignature. RandomGraphGenerator uses this method to 111 // generate a random list of operations in the graph. 112 const OperationSignature& getRandomOperation() const; 113 114 protected: 115 OperationManager() = default; 116 117 // Contains all operation signatures defined in operation_signatures/*.cpp. 118 // The signatures are sorted by name to ensure a predictable order. 119 std::map<std::string, const OperationSignature> mOperationSignatures; 120 121 // A subset of mOperationSignatures using by the random graph generator. 122 // This vector should be initialized by applyFilter() before generating the graph. 123 std::vector<OperationSignature> mFilteredSignatures; 124 }; 125 126 } // namespace fuzzing_test 127 } // namespace nn 128 } // namespace android 129 130 #endif // ANDROID_FRAMEWORK_ML_NN_RUNTIME_TEST_FUZZING_OPERATION_MANAGER_H 131