1// Protocol Buffers - Google's data interchange format
2// Copyright 2014 Google Inc.  All rights reserved.
3// https://developers.google.com/protocol-buffers/
4//
5// Redistribution and use in source and binary forms, with or without
6// modification, are permitted provided that the following conditions are
7// met:
8//
9//     * Redistributions of source code must retain the above copyright
10// notice, this list of conditions and the following disclaimer.
11//     * Redistributions in binary form must reproduce the above
12// copyright notice, this list of conditions and the following disclaimer
13// in the documentation and/or other materials provided with the
14// distribution.
15//     * Neither the name of Google Inc. nor the names of its
16// contributors may be used to endorse or promote products derived from
17// this software without specific prior written permission.
18//
19// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
22// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
23// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
25// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30
31#include <memory>
32
33#include <google/protobuf/compiler/ruby/ruby_generator.h>
34#include <google/protobuf/compiler/command_line_interface.h>
35#include <google/protobuf/io/zero_copy_stream.h>
36#include <google/protobuf/io/printer.h>
37
38#include <google/protobuf/testing/googletest.h>
39#include <gtest/gtest.h>
40#include <google/protobuf/testing/file.h>
41
42namespace google {
43namespace protobuf {
44namespace compiler {
45namespace ruby {
46namespace {
47
48string FindRubyTestDir(const string& file) {
49  // Inspired by TestSourceDir() in src/google/protobuf/testing/googletest.cc.
50#ifndef GOOGLE_THIRD_PARTY_PROTOBUF
51  string prefix = ".";
52  while (!File::Exists(prefix + "/src/google/protobuf/compiler/ruby" + file)) {
53    if (!File::Exists(prefix)) {
54      GOOGLE_LOG(FATAL)
55          << "Could not find Ruby test directory. Please run tests from "
56             "somewhere within the protobuf source package.";
57    }
58    prefix += "/..";
59  }
60  return prefix + "/src/google/protobuf/compiler/ruby";
61#else
62  return "third_party/protobuf/src/google/protobuf/compiler/ruby";
63#endif  // GOOGLE_THIRD_PARTY_PROTOBUF
64}
65
66// This test is a simple golden-file test over the output of the Ruby code
67// generator. When we make changes to the Ruby extension and alter the Ruby code
68// generator to use those changes, we should (i) manually test the output of the
69// code generator with the extension, and (ii) update the golden output above.
70// Some day, we may integrate build systems between protoc and the language
71// extensions to the point where we can do this test in a more automated way.
72
73TEST(RubyGeneratorTest, GeneratorTest) {
74  string ruby_tests = FindRubyTestDir("/ruby_generated_code.proto");
75
76  google::protobuf::compiler::CommandLineInterface cli;
77  cli.SetInputsAreProtoPathRelative(true);
78
79  ruby::Generator ruby_generator;
80  cli.RegisterGenerator("--ruby_out", &ruby_generator, "");
81
82  // Copy generated_code.proto to the temporary test directory.
83  string test_input;
84  GOOGLE_CHECK_OK(File::GetContents(
85      ruby_tests + "/ruby_generated_code.proto",
86      &test_input,
87      true));
88  GOOGLE_CHECK_OK(File::SetContents(
89      TestTempDir() + "/ruby_generated_code.proto",
90      test_input,
91      true));
92
93  // Invoke the proto compiler (we will be inside TestTempDir() at this point).
94  string ruby_out = "--ruby_out=" + TestTempDir();
95  string proto_path = "--proto_path=" + TestTempDir();
96  const char* argv[] = {
97    "protoc",
98    ruby_out.c_str(),
99    proto_path.c_str(),
100    "ruby_generated_code.proto",
101  };
102
103  EXPECT_EQ(0, cli.Run(4, argv));
104
105  // Load the generated output and compare to the expected result.
106  string output;
107  GOOGLE_CHECK_OK(File::GetContents(
108      TestTempDir() + "/ruby_generated_code.rb",
109      &output,
110      true));
111  string expected_output;
112  GOOGLE_CHECK_OK(File::GetContents(
113      ruby_tests + "/ruby_generated_code.rb",
114      &expected_output,
115      true));
116  EXPECT_EQ(expected_output, output);
117}
118
119}  // namespace
120}  // namespace ruby
121}  // namespace compiler
122}  // namespace protobuf
123}  // namespace google
124