/* * Copyright (C) 2015, 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 "options.h" #include <iostream> #include <memory> #include <string> #include <vector> #include <gtest/gtest.h> using std::cerr; using std::endl; using std::string; using std::unique_ptr; using std::vector; namespace android { namespace aidl { namespace { const char kPreprocessCommandOutputFile[] = "output_file_name"; const char kPreprocessCommandInput1[] = "input1.aidl"; const char kPreprocessCommandInput2[] = "input2.aidl"; const char kPreprocessCommandInput3[] = "input3.aidl"; const char* kPreprocessCommand[] = { "aidl", "--preprocess", kPreprocessCommandOutputFile, kPreprocessCommandInput1, kPreprocessCommandInput2, kPreprocessCommandInput3, nullptr, }; const char kCompileCommandInput[] = "directory/ITool.aidl"; const char kCompileCommandIncludePath[] = "-Iinclude_path"; const char* kCompileJavaCommand[] = { "aidl", "-b", kCompileCommandIncludePath, kCompileCommandInput, nullptr, }; const char kCompileCommandJavaOutput[] = "directory/ITool.java"; const char kCompileDepFileNinja[] = "--ninja"; const char* kCompileJavaCommandNinja[] = { "aidl", "-b", kCompileDepFileNinja, kCompileCommandIncludePath, kCompileCommandInput, nullptr, }; const char kCompileDepFile[] = "-doutput.deps"; const char kCompileCommandHeaderDir[] = "output/dir/"; const char kCompileCommandCppOutput[] = "some/file.cpp"; const char* kCompileCppCommand[] = { "aidl-cpp", kCompileCommandIncludePath, kCompileDepFile, kCompileCommandInput, kCompileCommandHeaderDir, kCompileCommandCppOutput, nullptr, }; const char* kCompileCppCommandNinja[] = { "aidl-cpp", kCompileCommandIncludePath, kCompileDepFile, kCompileDepFileNinja, kCompileCommandInput, kCompileCommandHeaderDir, kCompileCommandCppOutput, nullptr, }; unique_ptr<Options> GetOptions(const char* command[], Options::Language default_lang = Options::Language::JAVA) { int argc = 0; const char** command_part = command; for (; *command_part; ++argc, ++command_part) {} unique_ptr<Options> ret(new Options(argc, command, default_lang)); if (!ret->Ok()) { cerr << ret->GetErrorMessage(); cerr << "Failed to parse command line:"; for (int i = 0; i < argc; ++i) { cerr << " " << command[i]; cerr << endl; } } EXPECT_NE(ret, nullptr) << "Failed to parse options!"; return ret; } } // namespace TEST(OptionsTests, ParsesPreprocess) { unique_ptr<Options> options = GetOptions(kPreprocessCommand); EXPECT_EQ(Options::Task::PREPROCESS, options->GetTask()); EXPECT_EQ(false, options->FailOnParcelable()); EXPECT_EQ(0u, options->ImportDirs().size()); EXPECT_EQ(0u, options->PreprocessedFiles().size()); EXPECT_EQ(string{kPreprocessCommandOutputFile}, options->OutputFile()); EXPECT_EQ(false, options->AutoDepFile()); const vector<string> expected_input{kPreprocessCommandInput1, kPreprocessCommandInput2, kPreprocessCommandInput3}; EXPECT_EQ(expected_input, options->InputFiles()); } TEST(OptionsTests, ParsesCompileJava) { unique_ptr<Options> options = GetOptions(kCompileJavaCommand); EXPECT_EQ(Options::Task::COMPILE, options->GetTask()); EXPECT_EQ(Options::Language::JAVA, options->TargetLanguage()); EXPECT_EQ(true, options->FailOnParcelable()); EXPECT_EQ(1u, options->ImportDirs().size()); EXPECT_EQ(0u, options->PreprocessedFiles().size()); EXPECT_EQ(string{kCompileCommandInput}, options->InputFiles().front()); EXPECT_EQ(string{kCompileCommandJavaOutput}, options->OutputFile()); EXPECT_EQ(false, options->AutoDepFile()); EXPECT_EQ(false, options->DependencyFileNinja()); } TEST(OptionsTests, ParsesCompileJavaNinja) { unique_ptr<Options> options = GetOptions(kCompileJavaCommandNinja); EXPECT_EQ(Options::Task::COMPILE, options->GetTask()); EXPECT_EQ(Options::Language::JAVA, options->TargetLanguage()); EXPECT_EQ(true, options->FailOnParcelable()); EXPECT_EQ(1u, options->ImportDirs().size()); EXPECT_EQ(0u, options->PreprocessedFiles().size()); EXPECT_EQ(string{kCompileCommandInput}, options->InputFiles().front()); EXPECT_EQ(string{kCompileCommandJavaOutput}, options->OutputFile()); EXPECT_EQ(false, options->AutoDepFile()); EXPECT_EQ(true, options->DependencyFileNinja()); } TEST(OptionsTests, ParsesCompileCpp) { unique_ptr<Options> options = GetOptions(kCompileCppCommand, Options::Language::CPP); ASSERT_EQ(1u, options->ImportDirs().size()); EXPECT_EQ(string{kCompileCommandIncludePath}.substr(2), *options->ImportDirs().begin()); EXPECT_EQ(string{kCompileDepFile}.substr(2), options->DependencyFile()); EXPECT_EQ(false, options->DependencyFileNinja()); EXPECT_EQ(kCompileCommandInput, options->InputFiles().front()); EXPECT_EQ(kCompileCommandHeaderDir, options->OutputHeaderDir()); EXPECT_EQ(kCompileCommandCppOutput, options->OutputFile()); } TEST(OptionsTests, ParsesCompileCppNinja) { unique_ptr<Options> options = GetOptions(kCompileCppCommandNinja, Options::Language::CPP); ASSERT_EQ(1u, options->ImportDirs().size()); EXPECT_EQ(string{kCompileCommandIncludePath}.substr(2), *options->ImportDirs().begin()); EXPECT_EQ(string{kCompileDepFile}.substr(2), options->DependencyFile()); EXPECT_EQ(true, options->DependencyFileNinja()); EXPECT_EQ(kCompileCommandInput, options->InputFiles().front()); EXPECT_EQ(kCompileCommandHeaderDir, options->OutputHeaderDir()); EXPECT_EQ(kCompileCommandCppOutput, options->OutputFile()); } TEST(OptionsTests, ParsesCompileJavaMultiInput) { const char* argv[] = { "aidl", "--lang=java", kCompileCommandIncludePath, "-o src_out", "directory/input1.aidl", "directory/input2.aidl", "directory/input3.aidl", nullptr, }; unique_ptr<Options> options = GetOptions(argv); EXPECT_EQ(Options::Task::COMPILE, options->GetTask()); EXPECT_EQ(Options::Language::JAVA, options->TargetLanguage()); EXPECT_EQ(false, options->FailOnParcelable()); EXPECT_EQ(1u, options->ImportDirs().size()); EXPECT_EQ(0u, options->PreprocessedFiles().size()); const vector<string> expected_input{"directory/input1.aidl", "directory/input2.aidl", "directory/input3.aidl"}; EXPECT_EQ(expected_input, options->InputFiles()); EXPECT_EQ(string{""}, options->OutputFile()); EXPECT_EQ(false, options->AutoDepFile()); EXPECT_EQ(false, options->DependencyFileNinja()); EXPECT_EQ(string{""}, options->OutputHeaderDir()); EXPECT_EQ(string{"src_out/"}, options->OutputDir()); } TEST(OptionsTests, ParsesCompileJavaInvalid) { // -o option is required const char* arg_with_no_out_dir[] = { "aidl", "--lang=java", kCompileCommandIncludePath, "directory/input1.aidl", "directory/input2.aidl", "directory/input3.aidl", nullptr, }; EXPECT_EQ(false, GetOptions(arg_with_no_out_dir)->Ok()); // -h options is not for Java const char* arg_with_header_dir[] = { "aidl", "--lang=java", kCompileCommandIncludePath, "-o src_out", "-h header_out", "directory/input1.aidl", "directory/input2.aidl", "directory/input3.aidl", nullptr, }; EXPECT_EQ(false, GetOptions(arg_with_header_dir)->Ok()); } TEST(OptionsTests, ParsesCompileCppMultiInput) { const char* argv[] = { "aidl", "--lang=cpp", kCompileCommandIncludePath, "-h header_out", "-o src_out", "directory/input1.aidl", "directory/input2.aidl", "directory/input3.aidl", nullptr, }; unique_ptr<Options> options = GetOptions(argv); EXPECT_EQ(Options::Task::COMPILE, options->GetTask()); EXPECT_EQ(Options::Language::CPP, options->TargetLanguage()); EXPECT_EQ(false, options->FailOnParcelable()); EXPECT_EQ(1u, options->ImportDirs().size()); EXPECT_EQ(0u, options->PreprocessedFiles().size()); const vector<string> expected_input{"directory/input1.aidl", "directory/input2.aidl", "directory/input3.aidl"}; EXPECT_EQ(expected_input, options->InputFiles()); EXPECT_EQ(string{""}, options->OutputFile()); EXPECT_EQ(false, options->AutoDepFile()); EXPECT_EQ(false, options->DependencyFileNinja()); EXPECT_EQ(string{"header_out/"}, options->OutputHeaderDir()); EXPECT_EQ(string{"src_out/"}, options->OutputDir()); } TEST(OptionsTests, ParsesCompileCppInvalid) { // -o option is required const char* arg_with_no_out_dir[] = { "aidl", "--lang=cpp", kCompileCommandIncludePath, "directory/input1.aidl", "directory/input2.aidl", "directory/input3.aidl", nullptr, }; EXPECT_EQ(false, GetOptions(arg_with_no_out_dir)->Ok()); // -h options is required as well const char* arg_with_no_header_dir[] = { "aidl", "--lang=cpp", kCompileCommandIncludePath, "-o src_out", "directory/input1.aidl", "directory/input2.aidl", "directory/input3.aidl", nullptr, }; EXPECT_EQ(false, GetOptions(arg_with_no_header_dir)->Ok()); } } // namespace android } // namespace aidl