C++程序  |  327行  |  11.18 KB

/*
 * Copyright 2016 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "code_gen/driver/DriverCodeGenBase.h"

#include <iostream>
#include <string>

#include <hidl-util/Formatter.h>
#include <hidl-util/FQName.h>

#include "VtsCompilerUtils.h"
#include "utils/InterfaceSpecUtil.h"
#include "utils/StringUtil.h"

using namespace std;

namespace android {
namespace vts {

void DriverCodeGenBase::GenerateAll(
    Formatter& header_out, Formatter& source_out,
    const ComponentSpecificationMessage& message) {
  GenerateHeaderFile(header_out, message);
  GenerateSourceFile(source_out, message);
}

void DriverCodeGenBase::GenerateHeaderFile(
    Formatter& out, const ComponentSpecificationMessage& message) {
  string component_name = GetComponentName(message);
  if (component_name.empty()) {
    cerr << __func__ << ":" << __LINE__ << " error component_name is empty"
         << "\n";
    exit(-1);
  }

  string component_name_token;
  if (message.component_class() == HAL_HIDL) {
    FQName component_fq_name = GetFQName(message);
    component_name_token = component_fq_name.tokenName();
  } else {
    string version = GetVersion(message, true);
    component_name_token =
        ComponentClassToString(message.component_class()) + "_" +
        ComponentTypeToString(message.component_type()) + "_" + version;
  }
  string fuzzer_extended_class_name;
  if (message.component_class() == HAL_HIDL) {
    fuzzer_extended_class_name = "FuzzerExtended_" + component_name_token;
  } else {
    fuzzer_extended_class_name = "FuzzerExtended_" + GetComponentName(message);
  }

  out << "#ifndef __VTS_DRIVER__" << component_name_token << "__\n";
  out << "#define __VTS_DRIVER__" << component_name_token << "__\n";
  out << "\n";

  out << "#undef LOG_TAG\n";
  out << "#define LOG_TAG \"" << fuzzer_extended_class_name << "\"\n";

  GenerateHeaderIncludeFiles(out, message, fuzzer_extended_class_name);

  GenerateOpenNameSpaces(out, message);
  GenerateClassHeader(out, message, fuzzer_extended_class_name);
  out << "\n\n";
  GenerateHeaderGlobalFunctionDeclarations(out, message);
  GenerateCloseNameSpaces(out, message);
  out << "#endif" << "\n";
}

void DriverCodeGenBase::GenerateSourceFile(
    Formatter& out, const ComponentSpecificationMessage& message) {
  string component_name = GetComponentName(message);
  if (component_name.empty()) {
    cerr << __func__ << ":" << __LINE__ << " error component_name is empty"
         << "\n";
    exit(-1);
  }
  FQName component_fq_name = GetFQName(message);
  string component_name_token = component_fq_name.tokenName();
  string fuzzer_extended_class_name;
  if (message.component_class() == HAL_HIDL) {
    fuzzer_extended_class_name = "FuzzerExtended_" + component_name_token;
  } else {
    fuzzer_extended_class_name = "FuzzerExtended_" + GetComponentName(message);
  }
  GenerateSourceIncludeFiles(out, message, fuzzer_extended_class_name);
  out << "\n\n";
  GenerateOpenNameSpaces(out, message);
  GenerateClassImpl(out, message, fuzzer_extended_class_name);
  GenerateCppBodyGlobalFunctions(out, message, fuzzer_extended_class_name);
  GenerateCloseNameSpaces(out, message);
}

void DriverCodeGenBase::GenerateClassHeader(Formatter& out,
    const ComponentSpecificationMessage& message,
    const string& fuzzer_extended_class_name) {
  GenerateHeaderInterfaceImpl(out, message);
  out << "class " << fuzzer_extended_class_name << " : public DriverBase {"
      << "\n";
  out << " public:" << "\n";

  out.indent();
  GenerateClassConstructionFunction(out, message, fuzzer_extended_class_name);
  GeneratePublicFunctionDeclarations(out, message);
  out.unindent();

  out << " protected:" << "\n";

  out.indent();
  out << "bool Fuzz(FunctionSpecificationMessage* func_msg, void** result, "
      << "const string& callback_socket_name);\n";
  out << "bool CallFunction(const FunctionSpecificationMessage& func_msg, "
      << "const string& callback_socket_name, "
      << "FunctionSpecificationMessage* result_msg);\n";
  out << "bool VerifyResults(const FunctionSpecificationMessage& expected_result, "
      << "const FunctionSpecificationMessage& actual_result);\n";
  out << "bool GetAttribute(FunctionSpecificationMessage* func_msg, "
      << "void** result);\n";

  // Produce Fuzz method(s) for sub_struct(s).
  for (auto const& sub_struct : message.interface().sub_struct()) {
    GenerateFuzzFunctionForSubStruct(out, sub_struct, "_");
  }
  // Generate additional function declarations if any.
  GenerateAdditionalFuctionDeclarations(out, message,
                                        fuzzer_extended_class_name);
  out.unindent();

  out << " private:" << "\n";

  out.indent();
  // Generate declarations of private members if any.
  GeneratePrivateMemberDeclarations(out, message);
  out.unindent();

  out << "};\n";
}

void DriverCodeGenBase::GenerateClassImpl(Formatter& out,
    const ComponentSpecificationMessage& message,
    const string& fuzzer_extended_class_name) {
  GenerateCppBodyInterfaceImpl(out, message, fuzzer_extended_class_name);
  GenerateCppBodyFuzzFunction(out, message, fuzzer_extended_class_name);
  GenerateCppBodyGetAttributeFunction(out, message, fuzzer_extended_class_name);
  GenerateDriverFunctionImpl(out, message, fuzzer_extended_class_name);
  GenerateVerificationFunctionImpl(out, message, fuzzer_extended_class_name);
}

void DriverCodeGenBase::GenerateHeaderIncludeFiles(Formatter& out,
    const ComponentSpecificationMessage& message, const string&) {
  for (auto const& header : message.header()) {
    out << "#include " << header << "\n";
  }
  out << "\n";
  out << "#include <stdio.h>" << "\n";
  out << "#include <stdarg.h>" << "\n";
  out << "#include <stdlib.h>" << "\n";
  out << "#include <string.h>" << "\n";
  out << "#include <utils/Log.h>" << "\n";
  out << "\n";
  out << "#include <driver_base/DriverBase.h>"
      << "\n";
  out << "#include <driver_base/DriverCallbackBase.h>"
      << "\n";
  out << "\n";
  if (message.component_class() == HAL_HIDL) {
    out << "#include <VtsDriverCommUtil.h>" << "\n";
    out << "\n";
  }
}

void DriverCodeGenBase::GenerateSourceIncludeFiles(Formatter& out,
    const ComponentSpecificationMessage& message, const string&) {
  if (message.component_class() != HAL_HIDL) {
    out << "#include \"" << input_vts_file_path_ << ".h\"\n";
    for (auto const& header : message.header()) {
      out << "#include " << header << "\n";
    }
    out << "#include \"vts_datatype.h\"" << "\n";
  } else {
    out << "#include \"" << GetPackagePath(message) << "/"
        << GetVersion(message) << "/" << GetComponentBaseName(message)
        << ".vts.h\"\n";
  }
  out << "#include \"vts_measurement.h\"" << "\n";
  out << "#include <android-base/logging.h>"
      << "\n";
}

void DriverCodeGenBase::GenerateHeaderGlobalFunctionDeclarations(
    Formatter& out, const ComponentSpecificationMessage& message,
    const bool print_extern_block) {
  string function_name_prefix = GetFunctionNamePrefix(message);

  if (print_extern_block) {
    out << "extern \"C\" {" << "\n";
  }
  out << "extern "
      << "android::vts::DriverBase* " << function_name_prefix << "();\n";
  if (print_extern_block) {
    out << "}" << "\n";
  }
}

void DriverCodeGenBase::GenerateCppBodyGlobalFunctions(
    Formatter& out, const ComponentSpecificationMessage& message,
    const string& fuzzer_extended_class_name, const bool print_extern_block) {
  string function_name_prefix = GetFunctionNamePrefix(message);

  if (print_extern_block) {
    out << "extern \"C\" {" << "\n";
  }
  out << "android::vts::DriverBase* " << function_name_prefix << "() {\n";
  out.indent();
  out << "return (android::vts::DriverBase*) "
      << "new android::vts::";
  out << fuzzer_extended_class_name << "();\n";
  out.unindent();
  out << "}\n\n";
  if (print_extern_block) {
    out << "}\n";
  }
}

void DriverCodeGenBase::GenerateFuzzFunctionForSubStruct(
    Formatter& out, const StructSpecificationMessage& message,
    const string& parent_path) {
  out << "bool Fuzz_" << parent_path << message.name()
      << "(FunctionSpecificationMessage* func_msg," << "\n";
  out << "    void** result, const string& callback_socket_name);"
      << "\n";

  out << "bool GetAttribute_" << parent_path << message.name()
      << "(FunctionSpecificationMessage* /*func_msg*/,"
      << "\n";
  out << "    void** /*result*/);"
      << "\n";

  for (auto const& sub_struct : message.sub_struct()) {
    GenerateFuzzFunctionForSubStruct(out, sub_struct,
                                     parent_path + message.name() + "_");
  }
}

void DriverCodeGenBase::GenerateDriverFunctionImpl(Formatter& out,
    const ComponentSpecificationMessage& /*message*/,
    const string& fuzzer_extended_class_name) {
  out << "bool " << fuzzer_extended_class_name
      << "::CallFunction(const FunctionSpecificationMessage&, const string&, "
      << "FunctionSpecificationMessage* ) {\n";
  out.indent();
  out << "/* No implementation yet. */\n";
  out << "return true;\n";
  out.unindent();
  out << "}\n";
}

void DriverCodeGenBase::GenerateVerificationFunctionImpl(Formatter& out,
    const ComponentSpecificationMessage& /*message*/,
    const string& fuzzer_extended_class_name) {
  out << "bool " << fuzzer_extended_class_name
      << "::VerifyResults(const FunctionSpecificationMessage&, "
      << "const FunctionSpecificationMessage&) {\n";
  out.indent();
  out << "/* No implementation yet. */\n";
  out << "return true;\n";
  out.unindent();
  out << "}\n";
}

void DriverCodeGenBase::GenerateNamespaceName(
    Formatter& out, const ComponentSpecificationMessage& message) {
  if (message.component_class() == HAL_HIDL && message.has_package()) {
    out << GetPackageNamespaceToken(message)
        << "::" << GetVersion(message, true);
  } else {
    cerr << __func__ << ":" << __LINE__ << " no namespace" << "\n";
    exit(-1);
  }
}

void DriverCodeGenBase::GenerateOpenNameSpaces(Formatter& out,
    const ComponentSpecificationMessage& message) {
  if (message.component_class() == HAL_HIDL && message.has_package()) {
    out << "using namespace ";
    GenerateNamespaceName(out, message);
    out << ";" << "\n";
  }

  out << "namespace android {" << "\n";
  out << "namespace vts {" << "\n";
}

void DriverCodeGenBase::GenerateCloseNameSpaces(Formatter& out,
    const ComponentSpecificationMessage& /*message*/) {
  out << "}  // namespace vts" << "\n";
  out << "}  // namespace android" << "\n";
}

void DriverCodeGenBase::GenerateCodeToStartMeasurement(Formatter& out) {
  out << "VtsMeasurement vts_measurement;" << "\n";
  out << "vts_measurement.Start();" << "\n";
}

void DriverCodeGenBase::GenerateCodeToStopMeasurement(Formatter& out) {
  out << "vector<float>* measured = vts_measurement.Stop();" << "\n";
  out << "LOG(INFO) << \"time \" << (*measured)[0];"
      << "\n";
}

}  // namespace vts
}  // namespace android