Home | History | Annotate | Download | only in fuzzing
      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 operations 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