Imported Upstream version 1.8.0
[platform/core/ml/nnfw.git] / tests / nnfw_api / src / GenModelTests.cc
1 /*
2  * Copyright (c) 2020 Samsung Electronics Co., Ltd. All Rights Reserved
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 #include <gtest/gtest.h>
18 #include <nnfw_internal.h>
19
20 #include <fstream>
21
22 #include "CircleGen.h"
23 #include "fixtures.h"
24
25 /**
26  * @brief Generated Model test fixture for a one time inference
27  *
28  * This fixture is for one-time inference test with variety of generated models.
29  * It is the user's responsiblity to create @c _cbuf , @c _ref_inputs and @c _ref_outputs in the
30  * test body, which are generated circle buffer, model input data and output data respectively.
31  * The rest(calling API functions for execution) is done by @c Setup and @c TearDown .
32  *
33  */
34 class GenModelTest : public ::testing::Test
35 {
36 protected:
37   void SetUp() override { NNFW_ENSURE_SUCCESS(nnfw_create_session(&_so.session)); }
38
39   void TearDown() override
40   {
41     NNFW_ENSURE_SUCCESS(nnfw_load_circle_from_buffer(_so.session, _cbuf.buffer(), _cbuf.size()));
42     NNFW_ENSURE_SUCCESS(nnfw_prepare(_so.session));
43
44     // In/Out buffer settings
45     {
46       uint32_t num_inputs;
47       NNFW_ENSURE_SUCCESS(nnfw_input_size(_so.session, &num_inputs));
48       _so.inputs.resize(num_inputs);
49       for (uint32_t ind = 0; ind < _so.inputs.size(); ind++)
50       {
51         nnfw_tensorinfo ti;
52         NNFW_ENSURE_SUCCESS(nnfw_input_tensorinfo(_so.session, ind, &ti));
53         uint64_t input_elements = num_elems(&ti);
54         _so.inputs[ind].resize(input_elements);
55
56         ASSERT_EQ(nnfw_set_input(_so.session, ind, ti.dtype, _so.inputs[ind].data(),
57                                  sizeof(float) * input_elements),
58                   NNFW_STATUS_NO_ERROR);
59       }
60
61       uint32_t num_outputs;
62       NNFW_ENSURE_SUCCESS(nnfw_output_size(_so.session, &num_outputs));
63       _so.outputs.resize(num_outputs);
64       for (uint32_t ind = 0; ind < _so.outputs.size(); ind++)
65       {
66         nnfw_tensorinfo ti;
67         NNFW_ENSURE_SUCCESS(nnfw_output_tensorinfo(_so.session, ind, &ti));
68         uint64_t output_elements = num_elems(&ti);
69         _so.outputs[ind].resize(output_elements);
70         ASSERT_EQ(nnfw_set_output(_so.session, ind, ti.dtype, _so.outputs[ind].data(),
71                                   sizeof(float) * output_elements),
72                   NNFW_STATUS_NO_ERROR);
73       }
74     }
75
76     // Set input values, run, and check output values
77     {
78       ASSERT_EQ(_so.inputs.size(), _ref_inputs.size());
79       for (uint32_t i = 0; i < _so.inputs.size(); i++)
80       {
81         // Fill the values
82         ASSERT_EQ(_so.inputs[i].size(), _ref_inputs[i].size());
83         memcpy(_so.inputs[i].data(), _ref_inputs[i].data(), _so.inputs[i].size() * sizeof(float));
84       }
85
86       NNFW_ENSURE_SUCCESS(nnfw_run(_so.session));
87
88       ASSERT_EQ(_so.outputs.size(), _ref_outputs.size());
89       for (uint32_t i = 0; i < _so.outputs.size(); i++)
90       {
91         // Check output tensor values
92         auto &ref_output = _ref_outputs[i];
93         auto &output = _so.outputs[i];
94         ASSERT_EQ(output.size(), ref_output.size());
95         for (uint32_t e = 0; e < ref_output.size(); e++)
96           ASSERT_FLOAT_EQ(ref_output[e], output[e]);
97       }
98     }
99
100     NNFW_ENSURE_SUCCESS(nnfw_close_session(_so.session));
101   }
102
103 protected:
104   SessionObject _so;
105   CircleBuffer _cbuf;
106   std::vector<std::vector<float>> _ref_inputs;
107   std::vector<std::vector<float>> _ref_outputs;
108 };
109
110 TEST_F(GenModelTest, OneOp_Add_VarToConst)
111 {
112   CircleGen cgen;
113   std::vector<float> rhs_data{5, 4, 7, 4};
114   uint32_t rhs_buf = cgen.addBuffer(rhs_data);
115   int lhs = cgen.addTensor({{1, 2, 2, 1}, circle::TensorType::TensorType_FLOAT32});
116   int rhs = cgen.addTensor({{1, 2, 2, 1}, circle::TensorType::TensorType_FLOAT32, rhs_buf});
117   int out = cgen.addTensor({{1, 2, 2, 1}, circle::TensorType::TensorType_FLOAT32});
118   cgen.addOperatorAdd({{lhs, rhs}, {out}}, circle::ActivationFunctionType_NONE);
119   cgen.setInputsAndOutputs({lhs}, {out});
120   _cbuf = cgen.finish();
121
122   _ref_inputs = {{1, 3, 2, 4}};
123   _ref_outputs = {{6, 7, 9, 8}};
124 }
125
126 TEST_F(GenModelTest, OneOp_Add_VarToVar)
127 {
128   CircleGen cgen;
129   int lhs = cgen.addTensor({{1, 2, 2, 1}, circle::TensorType::TensorType_FLOAT32});
130   int rhs = cgen.addTensor({{1, 2, 2, 1}, circle::TensorType::TensorType_FLOAT32});
131   int out = cgen.addTensor({{1, 2, 2, 1}, circle::TensorType::TensorType_FLOAT32});
132   cgen.addOperatorAdd({{lhs, rhs}, {out}}, circle::ActivationFunctionType_NONE);
133   cgen.setInputsAndOutputs({lhs, rhs}, {out});
134   _cbuf = cgen.finish();
135
136   _ref_inputs = {{1, 3, 2, 4}, {5, 4, 7, 4}};
137   _ref_outputs = {{6, 7, 9, 8}};
138 }
139
140 TEST_F(GenModelTest, OneOp_AvgPool2D)
141 {
142   CircleGen cgen;
143   int in = cgen.addTensor({{1, 2, 2, 1}, circle::TensorType::TensorType_FLOAT32});
144   int out = cgen.addTensor({{1, 1, 1, 1}, circle::TensorType::TensorType_FLOAT32});
145   cgen.addOperatorAveragePool2D({{in}, {out}}, circle::Padding_SAME, 2, 2, 2, 2,
146                                 circle::ActivationFunctionType_NONE);
147   cgen.setInputsAndOutputs({in}, {out});
148   _cbuf = cgen.finish();
149
150   _ref_inputs = {{1, 3, 2, 4}};
151   _ref_outputs = {{2.5}};
152 }