Keun Soo Yim | b8edda3 | 2016-04-27 17:31:00 -0700 | [diff] [blame] | 1 | /* |
| 2 | * Copyright 2016 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 | #include "code_gen/HalCodeGen.h" |
| 18 | |
| 19 | #include <fstream> |
| 20 | #include <iostream> |
| 21 | #include <sstream> |
| 22 | #include <string> |
| 23 | |
Keun Soo Yim | f518585 | 2016-06-01 19:37:10 -0700 | [diff] [blame] | 24 | #include "test/vts/runners/host/proto/InterfaceSpecificationMessage.pb.h" |
Keun Soo Yim | b8edda3 | 2016-04-27 17:31:00 -0700 | [diff] [blame] | 25 | |
| 26 | #include "VtsCompilerUtils.h" |
| 27 | |
| 28 | using namespace std; |
| 29 | using namespace android; |
| 30 | |
| 31 | namespace android { |
| 32 | namespace vts { |
| 33 | |
| 34 | const char* const HalCodeGen::kInstanceVariableName = "device_"; |
| 35 | |
| 36 | |
Keun Soo Yim | 91d634a | 2016-06-02 11:38:00 -0700 | [diff] [blame^] | 37 | void ReplaceSubString(string& original, const string& from, const string& to) { |
| 38 | size_t index = 0; |
| 39 | int from_len = from.length(); |
| 40 | while (true) { |
| 41 | index = original.find(from, index); |
| 42 | if (index == std::string::npos) break; |
| 43 | original.replace(index, from_len, to); |
| 44 | index += from_len; |
| 45 | } |
| 46 | } |
| 47 | |
| 48 | |
Keun Soo Yim | b8edda3 | 2016-04-27 17:31:00 -0700 | [diff] [blame] | 49 | void HalCodeGen::GenerateCppBodyFuzzFunction( |
| 50 | std::stringstream& cpp_ss, |
| 51 | const InterfaceSpecificationMessage& message, |
| 52 | const string& fuzzer_extended_class_name) { |
Keun Soo Yim | 91d634a | 2016-06-02 11:38:00 -0700 | [diff] [blame^] | 53 | for (auto const& sub_struct : message.sub_struct()) { |
| 54 | GenerateCppBodyFuzzFunction( |
| 55 | cpp_ss, sub_struct, fuzzer_extended_class_name, |
| 56 | message.original_data_structure_name(), |
| 57 | sub_struct.is_pointer() ? "->" : "."); |
| 58 | } |
| 59 | |
Keun Soo Yim | b8edda3 | 2016-04-27 17:31:00 -0700 | [diff] [blame] | 60 | cpp_ss << "bool " << fuzzer_extended_class_name << "::Fuzz(" << endl; |
Keun Soo Yim | f518585 | 2016-06-01 19:37:10 -0700 | [diff] [blame] | 61 | cpp_ss << " FunctionSpecificationMessage* func_msg," << endl; |
Keun Soo Yim | b8edda3 | 2016-04-27 17:31:00 -0700 | [diff] [blame] | 62 | cpp_ss << " void** result) {" << endl; |
Keun Soo Yim | f518585 | 2016-06-01 19:37:10 -0700 | [diff] [blame] | 63 | cpp_ss << " const char* func_name = func_msg->name().c_str();" << endl; |
Keun Soo Yim | 91d634a | 2016-06-02 11:38:00 -0700 | [diff] [blame^] | 64 | cpp_ss << " cout << \"Function: \" << __func__ << \" \" << func_name << endl;" << endl; |
| 65 | |
| 66 | // to call another function if it's for a sub_struct |
| 67 | if (message.sub_struct().size() > 0) { |
| 68 | cpp_ss << " if (func_msg->parent_path().length() > 0) {" << endl; |
| 69 | for (auto const& sub_struct : message.sub_struct()) { |
| 70 | GenerateSubStructFuzzFunctionCall(cpp_ss, sub_struct, ""); |
| 71 | } |
| 72 | cpp_ss << " }" << endl; |
| 73 | } |
Keun Soo Yim | b8edda3 | 2016-04-27 17:31:00 -0700 | [diff] [blame] | 74 | |
| 75 | for (auto const& api : message.api()) { |
Keun Soo Yim | b8edda3 | 2016-04-27 17:31:00 -0700 | [diff] [blame] | 76 | cpp_ss << " if (!strcmp(func_name, \"" << api.name() << "\")) {" << endl; |
| 77 | |
| 78 | // args - definition; |
| 79 | int arg_count = 0; |
| 80 | for (auto const& arg : api.arg()) { |
| 81 | cpp_ss << " " << GetCppVariableType(arg) << " "; |
| 82 | cpp_ss << "arg" << arg_count << " = "; |
| 83 | if (arg_count == 0 |
Keun Soo Yim | a8cf69a | 2016-05-18 18:11:37 -0700 | [diff] [blame] | 84 | && arg.aggregate_type().size() == 1 |
| 85 | && !strncmp(arg.aggregate_type(0).c_str(), |
Keun Soo Yim | b8edda3 | 2016-04-27 17:31:00 -0700 | [diff] [blame] | 86 | message.original_data_structure_name().c_str(), |
| 87 | message.original_data_structure_name().length())) { |
| 88 | cpp_ss << "reinterpret_cast<" << GetCppVariableType(arg) << ">(" |
| 89 | << kInstanceVariableName << ")"; |
| 90 | } else { |
Keun Soo Yim | 34067de | 2016-05-17 09:46:37 -0700 | [diff] [blame] | 91 | std::stringstream msg_ss; |
Keun Soo Yim | f518585 | 2016-06-01 19:37:10 -0700 | [diff] [blame] | 92 | msg_ss << "func_msg->arg(" << arg_count << ")"; |
Keun Soo Yim | 34067de | 2016-05-17 09:46:37 -0700 | [diff] [blame] | 93 | string msg = msg_ss.str(); |
| 94 | |
Keun Soo Yim | 0ae2f74 | 2016-06-01 14:36:01 -0700 | [diff] [blame] | 95 | if (arg.primitive_type().size() > 0) { |
Keun Soo Yim | f518585 | 2016-06-01 19:37:10 -0700 | [diff] [blame] | 96 | cpp_ss << "(" << msg << ".aggregate_type().size() == 0 && " |
| 97 | << msg << ".primitive_type().size() == 1)? "; |
Keun Soo Yim | 0ae2f74 | 2016-06-01 14:36:01 -0700 | [diff] [blame] | 98 | if (!strcmp(arg.primitive_type(0).c_str(), "pointer") |
| 99 | || !strcmp(arg.primitive_type(0).c_str(), "char_pointer") |
Keun Soo Yim | 91d634a | 2016-06-02 11:38:00 -0700 | [diff] [blame^] | 100 | || !strcmp(arg.primitive_type(0).c_str(), "void_pointer") |
Keun Soo Yim | 0ae2f74 | 2016-06-01 14:36:01 -0700 | [diff] [blame] | 101 | || !strcmp(arg.primitive_type(0).c_str(), "function_pointer")) { |
| 102 | cpp_ss << "reinterpret_cast<" << GetCppVariableType(arg) << ">"; |
| 103 | } |
| 104 | cpp_ss << "(" << msg << ".primitive_value(0)"; |
| 105 | |
| 106 | if (arg.primitive_type(0) == "int32_t" |
| 107 | || arg.primitive_type(0) == "uint32_t" |
| 108 | || arg.primitive_type(0) == "int64_t" |
| 109 | || arg.primitive_type(0) == "uint64_t" |
| 110 | || arg.primitive_type(0) == "int16_t" |
| 111 | || arg.primitive_type(0) == "uint16_t" |
| 112 | || arg.primitive_type(0) == "int8_t" |
| 113 | || arg.primitive_type(0) == "uint8_t" |
| 114 | || arg.primitive_type(0) == "float_t" |
| 115 | || arg.primitive_type(0) == "double_t") { |
| 116 | cpp_ss << "." << arg.primitive_type(0) << "() "; |
| 117 | } else if (!strcmp(arg.primitive_type(0).c_str(), "pointer")) { |
| 118 | cpp_ss << ".pointer() "; |
| 119 | } else if (!strcmp(arg.primitive_type(0).c_str(), "char_pointer")) { |
| 120 | cpp_ss << ".pointer() "; |
| 121 | } else if (!strcmp(arg.primitive_type(0).c_str(), "function_pointer")) { |
| 122 | cpp_ss << ".pointer() "; |
Keun Soo Yim | 91d634a | 2016-06-02 11:38:00 -0700 | [diff] [blame^] | 123 | } else if (!strcmp(arg.primitive_type(0).c_str(), "void_pointer")) { |
| 124 | cpp_ss << ".pointer() "; |
Keun Soo Yim | 0ae2f74 | 2016-06-01 14:36:01 -0700 | [diff] [blame] | 125 | } else { |
| 126 | cerr << __func__ << " ERROR unsupported type " << arg.primitive_type(0) << endl; |
| 127 | exit(-1); |
| 128 | } |
| 129 | cpp_ss << ") : "; |
| 130 | } |
| 131 | |
Keun Soo Yim | f518585 | 2016-06-01 19:37:10 -0700 | [diff] [blame] | 132 | cpp_ss << "( (" << msg << ".aggregate_value_size() > 0 || " |
| 133 | << msg << ".primitive_value_size() > 0)? "; |
Keun Soo Yim | 34067de | 2016-05-17 09:46:37 -0700 | [diff] [blame] | 134 | cpp_ss << GetCppInstanceType(arg, msg); |
Keun Soo Yim | 0ae2f74 | 2016-06-01 14:36:01 -0700 | [diff] [blame] | 135 | cpp_ss << " : " << GetCppInstanceType(arg) << " )"; |
| 136 | // TODO: use the given message and call a lib function which converts |
| 137 | // a message to a C/C++ struct. |
Keun Soo Yim | b8edda3 | 2016-04-27 17:31:00 -0700 | [diff] [blame] | 138 | } |
| 139 | cpp_ss << ";" << endl; |
| 140 | cpp_ss << " cout << \"arg" << arg_count << " = \" << arg" << arg_count |
| 141 | << " << endl;" << endl; |
| 142 | arg_count++; |
| 143 | } |
| 144 | |
| 145 | // actual function call |
Keun Soo Yim | ffb07ba | 2016-05-18 16:22:45 -0700 | [diff] [blame] | 146 | GenerateCodeToStartMeasurement(cpp_ss); |
Keun Soo Yim | 6d94495 | 2016-05-31 16:30:56 -0700 | [diff] [blame] | 147 | cpp_ss << " cout << \"hit2.\" << device_ << endl;" << endl; |
| 148 | |
| 149 | cpp_ss << " " << message.original_data_structure_name() |
| 150 | << "* local_device = "; |
| 151 | cpp_ss << "reinterpret_cast<" << message.original_data_structure_name() |
| 152 | << "*>(" << kInstanceVariableName << ");" << endl; |
| 153 | |
| 154 | cpp_ss << " if (local_device == NULL) {" << endl; |
| 155 | cpp_ss << " cout << \"use hmi\" << endl;" << endl; |
Keun Soo Yim | 91d634a | 2016-06-02 11:38:00 -0700 | [diff] [blame^] | 156 | cpp_ss << " local_device = reinterpret_cast<" |
| 157 | << message.original_data_structure_name() << "*>(hmi_);" << endl; |
Keun Soo Yim | 6d94495 | 2016-05-31 16:30:56 -0700 | [diff] [blame] | 158 | cpp_ss << " }" << endl; |
| 159 | cpp_ss << " if (local_device == NULL) {" << endl; |
| 160 | cpp_ss << " cerr << \"both device_ and hmi_ are NULL.\" << endl;" << endl; |
| 161 | cpp_ss << " return false;" << endl; |
| 162 | cpp_ss << " }" << endl; |
| 163 | cpp_ss << " if (reinterpret_cast<" << message.original_data_structure_name() |
| 164 | << "*>(local_device)->" << api.name() << " == NULL"; |
| 165 | cpp_ss << ") {" << endl; |
| 166 | cpp_ss << " cerr << \"api not set.\" << endl;" << endl; |
| 167 | // todo: consider throwing an exception at least a way to tell more |
| 168 | // specifically to the caller. |
| 169 | cpp_ss << " return false;" << endl; |
| 170 | cpp_ss << " }" << endl; |
| 171 | |
| 172 | cpp_ss << " cout << \"ok. let's call.\" << endl;" << endl; |
Keun Soo Yim | b8edda3 | 2016-04-27 17:31:00 -0700 | [diff] [blame] | 173 | cpp_ss << " "; |
Keun Soo Yim | a8cf69a | 2016-05-18 18:11:37 -0700 | [diff] [blame] | 174 | if (api.return_type().primitive_type().size() == 1 |
| 175 | && !strcmp(api.return_type().primitive_type(0).c_str(), "void")) { |
Keun Soo Yim | b8edda3 | 2016-04-27 17:31:00 -0700 | [diff] [blame] | 176 | cpp_ss << "*result = NULL;" << endl; |
| 177 | } else { |
| 178 | cpp_ss << "*result = const_cast<void*>(reinterpret_cast<const void*>("; |
| 179 | } |
Keun Soo Yim | 6d94495 | 2016-05-31 16:30:56 -0700 | [diff] [blame] | 180 | cpp_ss << "local_device->" << api.name() << "("; |
Keun Soo Yim | b8edda3 | 2016-04-27 17:31:00 -0700 | [diff] [blame] | 181 | if (arg_count > 0) cpp_ss << endl; |
| 182 | |
| 183 | for (int index = 0; index < arg_count; index++) { |
| 184 | cpp_ss << " arg" << index; |
| 185 | if (index != (arg_count - 1)) { |
| 186 | cpp_ss << "," << endl; |
| 187 | } |
| 188 | } |
Keun Soo Yim | a8cf69a | 2016-05-18 18:11:37 -0700 | [diff] [blame] | 189 | if (api.return_type().primitive_type().size() == 0 |
| 190 | || (api.return_type().primitive_type().size() == 1 |
| 191 | && strcmp(api.return_type().primitive_type(0).c_str(), "void"))) { |
Keun Soo Yim | b8edda3 | 2016-04-27 17:31:00 -0700 | [diff] [blame] | 192 | cpp_ss << "))"; |
| 193 | } |
| 194 | cpp_ss << ");" << endl; |
Keun Soo Yim | ffb07ba | 2016-05-18 16:22:45 -0700 | [diff] [blame] | 195 | GenerateCodeToStopMeasurement(cpp_ss); |
Keun Soo Yim | 6d94495 | 2016-05-31 16:30:56 -0700 | [diff] [blame] | 196 | cpp_ss << " cout << \"called\" << endl;" << endl; |
Keun Soo Yim | 0ae2f74 | 2016-06-01 14:36:01 -0700 | [diff] [blame] | 197 | |
| 198 | // Copy the output (call by pointer or reference cases). |
| 199 | arg_count = 0; |
| 200 | for (auto const& arg : api.arg()) { |
| 201 | if (arg.is_output()) { |
| 202 | // TODO check the return value |
| 203 | cpp_ss << " " << GetConversionToProtobufFunctionName(arg) |
| 204 | << "(arg" << arg_count << ", " |
Keun Soo Yim | f518585 | 2016-06-01 19:37:10 -0700 | [diff] [blame] | 205 | << "func_msg->mutable_arg(" << arg_count << "));" << endl; |
Keun Soo Yim | 0ae2f74 | 2016-06-01 14:36:01 -0700 | [diff] [blame] | 206 | } |
| 207 | arg_count++; |
| 208 | } |
| 209 | |
Keun Soo Yim | b8edda3 | 2016-04-27 17:31:00 -0700 | [diff] [blame] | 210 | cpp_ss << " return true;" << endl; |
| 211 | cpp_ss << " }" << endl; |
| 212 | } |
| 213 | // TODO: if there were pointers, free them. |
| 214 | cpp_ss << " return false;" << endl; |
| 215 | cpp_ss << "}" << endl; |
| 216 | } |
| 217 | |
| 218 | |
Keun Soo Yim | 91d634a | 2016-06-02 11:38:00 -0700 | [diff] [blame^] | 219 | void HalCodeGen::GenerateCppBodyFuzzFunction( |
| 220 | std::stringstream& cpp_ss, |
| 221 | const StructSpecificationMessage& message, |
| 222 | const string& fuzzer_extended_class_name, |
| 223 | const string& original_data_structure_name, |
| 224 | const string& parent_path) { |
| 225 | for (auto const& sub_struct : message.sub_struct()) { |
| 226 | GenerateCppBodyFuzzFunction( |
| 227 | cpp_ss, sub_struct, fuzzer_extended_class_name, |
| 228 | original_data_structure_name, |
| 229 | parent_path + message.name() + (sub_struct.is_pointer() ? "->" : ".")); |
| 230 | } |
| 231 | |
| 232 | string parent_path_printable(parent_path); |
| 233 | ReplaceSubString(parent_path_printable, "->", "_"); |
| 234 | replace(parent_path_printable.begin(), parent_path_printable.end(), '.', '_'); |
| 235 | |
| 236 | cpp_ss << "bool " << fuzzer_extended_class_name << "::Fuzz_" |
| 237 | << parent_path_printable + message.name() << "(" << endl; |
| 238 | cpp_ss << " FunctionSpecificationMessage* func_msg," << endl; |
| 239 | cpp_ss << " void** result) {" << endl; |
| 240 | cpp_ss << " const char* func_name = func_msg->name().c_str();" << endl; |
| 241 | cpp_ss << " cout << \"Function: \" << __func__ << \" \" << func_name << endl;" << endl; |
| 242 | |
| 243 | for (auto const& api : message.api()) { |
| 244 | cpp_ss << " if (!strcmp(func_name, \"" << api.name() << "\")) {" << endl; |
| 245 | |
| 246 | // args - definition; |
| 247 | int arg_count = 0; |
| 248 | for (auto const& arg : api.arg()) { |
| 249 | cpp_ss << " " << GetCppVariableType(arg) << " "; |
| 250 | cpp_ss << "arg" << arg_count << " = "; |
| 251 | if (arg_count == 0 |
| 252 | && arg.aggregate_type().size() == 1 |
| 253 | && !strncmp(arg.aggregate_type(0).c_str(), |
| 254 | original_data_structure_name.c_str(), |
| 255 | original_data_structure_name.length())) { |
| 256 | cpp_ss << "reinterpret_cast<" << GetCppVariableType(arg) << ">(" |
| 257 | << kInstanceVariableName << ")"; |
| 258 | } else { |
| 259 | std::stringstream msg_ss; |
| 260 | msg_ss << "func_msg->arg(" << arg_count << ")"; |
| 261 | string msg = msg_ss.str(); |
| 262 | |
| 263 | if (arg.primitive_type().size() > 0) { |
| 264 | cpp_ss << "(" << msg << ".aggregate_type().size() == 0 && " |
| 265 | << msg << ".primitive_type().size() == 1)? "; |
| 266 | if (!strcmp(arg.primitive_type(0).c_str(), "pointer") |
| 267 | || !strcmp(arg.primitive_type(0).c_str(), "char_pointer") |
| 268 | || !strcmp(arg.primitive_type(0).c_str(), "void_pointer") |
| 269 | || !strcmp(arg.primitive_type(0).c_str(), "function_pointer")) { |
| 270 | cpp_ss << "reinterpret_cast<" << GetCppVariableType(arg) << ">"; |
| 271 | } |
| 272 | cpp_ss << "(" << msg << ".primitive_value(0)"; |
| 273 | |
| 274 | if (arg.primitive_type(0) == "int32_t" |
| 275 | || arg.primitive_type(0) == "uint32_t" |
| 276 | || arg.primitive_type(0) == "int64_t" |
| 277 | || arg.primitive_type(0) == "uint64_t" |
| 278 | || arg.primitive_type(0) == "int16_t" |
| 279 | || arg.primitive_type(0) == "uint16_t" |
| 280 | || arg.primitive_type(0) == "int8_t" |
| 281 | || arg.primitive_type(0) == "uint8_t" |
| 282 | || arg.primitive_type(0) == "float_t" |
| 283 | || arg.primitive_type(0) == "double_t") { |
| 284 | cpp_ss << "." << arg.primitive_type(0) << "() "; |
| 285 | } else if (!strcmp(arg.primitive_type(0).c_str(), "pointer")) { |
| 286 | cpp_ss << ".pointer() "; |
| 287 | } else if (!strcmp(arg.primitive_type(0).c_str(), "char_pointer")) { |
| 288 | cpp_ss << ".pointer() "; |
| 289 | } else if (!strcmp(arg.primitive_type(0).c_str(), "function_pointer")) { |
| 290 | cpp_ss << ".pointer() "; |
| 291 | } else if (!strcmp(arg.primitive_type(0).c_str(), "void_pointer")) { |
| 292 | cpp_ss << ".pointer() "; |
| 293 | } else { |
| 294 | cerr << __func__ << " ERROR unsupported type " << arg.primitive_type(0) << endl; |
| 295 | exit(-1); |
| 296 | } |
| 297 | cpp_ss << ") : "; |
| 298 | } |
| 299 | |
| 300 | cpp_ss << "( (" << msg << ".aggregate_value_size() > 0 || " |
| 301 | << msg << ".primitive_value_size() > 0)? "; |
| 302 | cpp_ss << GetCppInstanceType(arg, msg); |
| 303 | cpp_ss << " : " << GetCppInstanceType(arg) << " )"; |
| 304 | // TODO: use the given message and call a lib function which converts |
| 305 | // a message to a C/C++ struct. |
| 306 | } |
| 307 | cpp_ss << ";" << endl; |
| 308 | cpp_ss << " cout << \"arg" << arg_count << " = \" << arg" << arg_count |
| 309 | << " << endl;" << endl; |
| 310 | arg_count++; |
| 311 | } |
| 312 | |
| 313 | // actual function call |
| 314 | GenerateCodeToStartMeasurement(cpp_ss); |
| 315 | cpp_ss << " cout << \"hit2.\" << device_ << endl;" << endl; |
| 316 | |
| 317 | cpp_ss << " " << original_data_structure_name |
| 318 | << "* local_device = "; |
| 319 | cpp_ss << "reinterpret_cast<" << original_data_structure_name |
| 320 | << "*>(" << kInstanceVariableName << ");" << endl; |
| 321 | |
| 322 | cpp_ss << " if (local_device == NULL) {" << endl; |
| 323 | cpp_ss << " cout << \"use hmi\" << endl;" << endl; |
| 324 | cpp_ss << " local_device = reinterpret_cast<" << original_data_structure_name |
| 325 | << "*>(hmi_);" << endl; |
| 326 | cpp_ss << " }" << endl; |
| 327 | cpp_ss << " if (local_device == NULL) {" << endl; |
| 328 | cpp_ss << " cerr << \"both device_ and hmi_ are NULL.\" << endl;" << endl; |
| 329 | cpp_ss << " return false;" << endl; |
| 330 | cpp_ss << " }" << endl; |
| 331 | cpp_ss << " if (reinterpret_cast<" << original_data_structure_name |
| 332 | << "*>(local_device)" << parent_path |
| 333 | << message.name() << "->" << api.name() << " == NULL"; |
| 334 | cpp_ss << ") {" << endl; |
| 335 | cpp_ss << " cerr << \"api not set.\" << endl;" << endl; |
| 336 | // todo: consider throwing an exception at least a way to tell more |
| 337 | // specifically to the caller. |
| 338 | cpp_ss << " return false;" << endl; |
| 339 | cpp_ss << " }" << endl; |
| 340 | |
| 341 | cpp_ss << " cout << \"ok. let's call.\" << endl;" << endl; |
| 342 | cpp_ss << " "; |
| 343 | if (api.return_type().primitive_type().size() == 1 |
| 344 | && !strcmp(api.return_type().primitive_type(0).c_str(), "void")) { |
| 345 | cpp_ss << "*result = NULL;" << endl; |
| 346 | } else { |
| 347 | cpp_ss << "*result = const_cast<void*>(reinterpret_cast<const void*>("; |
| 348 | } |
| 349 | cpp_ss << "local_device" << parent_path |
| 350 | << message.name() << "->" << api.name() << "("; |
| 351 | if (arg_count > 0) cpp_ss << endl; |
| 352 | |
| 353 | for (int index = 0; index < arg_count; index++) { |
| 354 | cpp_ss << " arg" << index; |
| 355 | if (index != (arg_count - 1)) { |
| 356 | cpp_ss << "," << endl; |
| 357 | } |
| 358 | } |
| 359 | if (api.return_type().primitive_type().size() == 0 |
| 360 | || (api.return_type().primitive_type().size() == 1 |
| 361 | && strcmp(api.return_type().primitive_type(0).c_str(), "void"))) { |
| 362 | cpp_ss << "))"; |
| 363 | } |
| 364 | cpp_ss << ");" << endl; |
| 365 | GenerateCodeToStopMeasurement(cpp_ss); |
| 366 | cpp_ss << " cout << \"called\" << endl;" << endl; |
| 367 | |
| 368 | // Copy the output (call by pointer or reference cases). |
| 369 | arg_count = 0; |
| 370 | for (auto const& arg : api.arg()) { |
| 371 | if (arg.is_output()) { |
| 372 | // TODO check the return value |
| 373 | cpp_ss << " " << GetConversionToProtobufFunctionName(arg) |
| 374 | << "(arg" << arg_count << ", " |
| 375 | << "func_msg->mutable_arg(" << arg_count << "));" << endl; |
| 376 | } |
| 377 | arg_count++; |
| 378 | } |
| 379 | |
| 380 | cpp_ss << " return true;" << endl; |
| 381 | cpp_ss << " }" << endl; |
| 382 | } |
| 383 | // TODO: if there were pointers, free them. |
| 384 | cpp_ss << " return false;" << endl; |
| 385 | cpp_ss << "}" << endl; |
| 386 | } |
| 387 | |
| 388 | |
Keun Soo Yim | b8edda3 | 2016-04-27 17:31:00 -0700 | [diff] [blame] | 389 | void HalCodeGen::GenerateHeaderGlobalFunctionDeclarations( |
| 390 | std::stringstream& h_ss, |
| 391 | const string& function_prototype) { |
| 392 | h_ss << "extern \"C\" {" << endl; |
| 393 | h_ss << "extern " << function_prototype << ";" << endl; |
| 394 | h_ss << "}" << endl; |
| 395 | } |
| 396 | |
| 397 | |
| 398 | void HalCodeGen::GenerateCppBodyGlobalFunctions( |
| 399 | std::stringstream& cpp_ss, |
| 400 | const string& function_prototype, |
| 401 | const string& fuzzer_extended_class_name) { |
| 402 | cpp_ss << "extern \"C\" {" << endl; |
| 403 | cpp_ss << function_prototype << " {" << endl; |
| 404 | cpp_ss << " return (android::vts::FuzzerBase*) " |
| 405 | << "new android::vts::" << fuzzer_extended_class_name << "();" << endl; |
| 406 | cpp_ss << "}" << endl << endl; |
| 407 | cpp_ss << "}" << endl; |
| 408 | } |
| 409 | |
Keun Soo Yim | 91d634a | 2016-06-02 11:38:00 -0700 | [diff] [blame^] | 410 | |
| 411 | void HalCodeGen::GenerateSubStructFuzzFunctionCall( |
| 412 | std::stringstream& cpp_ss, |
| 413 | const StructSpecificationMessage& message, |
| 414 | const string& parent_path) { |
| 415 | string current_path(parent_path); |
| 416 | if (current_path.length() > 0) { |
| 417 | current_path += "."; |
| 418 | } |
| 419 | current_path += message.name(); |
| 420 | |
| 421 | string current_path_printable(current_path); |
| 422 | replace(current_path_printable.begin(), current_path_printable.end(), '.', '_'); |
| 423 | |
| 424 | cpp_ss << " if (func_msg->parent_path() == \"" << current_path << "\") {" << endl; |
| 425 | cpp_ss << " return Fuzz__" << current_path_printable << "(func_msg, result);"<< endl; |
| 426 | cpp_ss << " }" << endl; |
| 427 | |
| 428 | for (auto const& sub_struct : message.sub_struct()) { |
| 429 | GenerateSubStructFuzzFunctionCall( |
| 430 | cpp_ss, sub_struct, current_path); |
| 431 | } |
| 432 | } |
| 433 | |
Keun Soo Yim | b8edda3 | 2016-04-27 17:31:00 -0700 | [diff] [blame] | 434 | } // namespace vts |
| 435 | } // namespace android |