• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Protocol Buffers - Google's data interchange format
2 // Copyright 2014 Google Inc.  All rights reserved.
3 //
4 // Use of this source code is governed by a BSD-style
5 // license that can be found in the LICENSE file or at
6 // https://developers.google.com/open-source/licenses/bsd
7 
8 #include "google/protobuf/compiler/objectivec/line_consumer.h"
9 
10 #include <string>
11 #include <tuple>
12 #include <utility>
13 #include <vector>
14 
15 #include <gtest/gtest.h>
16 #include "absl/base/macros.h"
17 #include "absl/strings/str_cat.h"
18 #include "absl/strings/string_view.h"
19 #include "google/protobuf/io/zero_copy_stream_impl_lite.h"
20 
21 namespace google {
22 namespace protobuf {
23 namespace compiler {
24 namespace objectivec {
25 
26 namespace {
27 
28 class TestLineCollector : public LineConsumer {
29  public:
TestLineCollector(std::vector<std::string> * inout_lines,const std::string * reject_line=nullptr,bool skip_msg=false)30   explicit TestLineCollector(std::vector<std::string>* inout_lines,
31                              const std::string* reject_line = nullptr,
32                              bool skip_msg = false)
33       : lines_(inout_lines), reject_(reject_line), skip_msg_(skip_msg) {}
34 
ConsumeLine(absl::string_view line,std::string * out_error)35   bool ConsumeLine(absl::string_view line, std::string* out_error) override {
36     if (reject_ && *reject_ == line) {
37       if (!skip_msg_) {
38         *out_error = absl::StrCat("Rejected '", *reject_, "'");
39       }
40       return false;
41     }
42     if (lines_) {
43       lines_->emplace_back(line);
44     }
45     return true;
46   }
47 
48  private:
49   std::vector<std::string>* lines_;
50   const std::string* reject_;
51   bool skip_msg_;
52 };
53 
54 const int kBlockSizes[] = {-1, 1, 2, 5, 64};
55 const int kBlockSizeCount = ABSL_ARRAYSIZE(kBlockSizes);
56 
TEST(ObjCHelper,ParseSimple_BasicsSuccess)57 TEST(ObjCHelper, ParseSimple_BasicsSuccess) {
58   const std::vector<std::pair<std::string, std::vector<std::string>>> tests = {
59       {"", {}},
60       {"a", {"a"}},
61       {"a c", {"a c"}},
62       {" a c ", {"a c"}},
63       {"\ta c ", {"a c"}},
64       {"abc\n", {"abc"}},
65       {"abc\nd f", {"abc", "d f"}},
66       {"\n abc \n def \n\n", {"abc", "def"}},
67   };
68 
69   for (const auto& test : tests) {
70     for (int i = 0; i < kBlockSizeCount; i++) {
71       io::ArrayInputStream input(test.first.data(), test.first.size(),
72                                  kBlockSizes[i]);
73       std::string err_str;
74       std::vector<std::string> lines;
75       TestLineCollector collector(&lines);
76       EXPECT_TRUE(ParseSimpleStream(input, "dummy", &collector, &err_str));
77       EXPECT_EQ(lines, test.second);
78       EXPECT_TRUE(err_str.empty());
79     }
80   }
81 }
82 
TEST(ObjCHelper,ParseSimple_DropsComments)83 TEST(ObjCHelper, ParseSimple_DropsComments) {
84   const std::vector<std::pair<std::string, std::vector<std::string>>> tests = {
85       {"# nothing", {}},
86       {"#", {}},
87       {"##", {}},
88       {"\n# nothing\n", {}},
89       {"a # same line", {"a"}},
90       {"a # same line\n", {"a"}},
91       {"a\n# line\nc", {"a", "c"}},
92       {"# n o t # h i n g #", {}},
93       {"## n o # t h i n g #", {}},
94       {"a# n o t # h i n g #", {"a"}},
95       {"a\n## n o # t h i n g #", {"a"}},
96   };
97 
98   for (const auto& test : tests) {
99     for (int i = 0; i < kBlockSizeCount; i++) {
100       io::ArrayInputStream input(test.first.data(), test.first.size(),
101                                  kBlockSizes[i]);
102       std::string err_str;
103       std::vector<std::string> lines;
104       TestLineCollector collector(&lines);
105       EXPECT_TRUE(ParseSimpleStream(input, "dummy", &collector, &err_str));
106       EXPECT_EQ(lines, test.second);
107       EXPECT_TRUE(err_str.empty());
108     }
109   }
110 }
111 
TEST(ObjCHelper,ParseSimple_RejectLines)112 TEST(ObjCHelper, ParseSimple_RejectLines) {
113   const std::vector<std::tuple<std::string, std::string, int>> tests = {
114       std::make_tuple("a\nb\nc", "a", 1),
115       std::make_tuple("a\nb\nc", "b", 2),
116       std::make_tuple("a\nb\nc", "c", 3),
117       std::make_tuple("a\nb\nc\n", "c", 3),
118   };
119 
120   for (const auto& test : tests) {
121     for (int i = 0; i < kBlockSizeCount; i++) {
122       io::ArrayInputStream input(std::get<0>(test).data(),
123                                  std::get<0>(test).size(), kBlockSizes[i]);
124       std::string err_str;
125       TestLineCollector collector(nullptr, &std::get<1>(test));
126       EXPECT_FALSE(ParseSimpleStream(input, "dummy", &collector, &err_str));
127       std::string expected_err =
128           absl::StrCat("error: dummy Line ", std::get<2>(test), ", Rejected '",
129                        std::get<1>(test), "'");
130       EXPECT_EQ(err_str, expected_err);
131     }
132   }
133 }
134 
TEST(ObjCHelper,ParseSimple_RejectLinesNoMessage)135 TEST(ObjCHelper, ParseSimple_RejectLinesNoMessage) {
136   const std::vector<std::tuple<std::string, std::string, int>> tests = {
137       std::make_tuple("a\nb\nc", "a", 1),
138       std::make_tuple("a\nb\nc", "b", 2),
139       std::make_tuple("a\nb\nc", "c", 3),
140       std::make_tuple("a\nb\nc\n", "c", 3),
141   };
142 
143   for (const auto& test : tests) {
144     for (int i = 0; i < kBlockSizeCount; i++) {
145       io::ArrayInputStream input(std::get<0>(test).data(),
146                                  std::get<0>(test).size(), kBlockSizes[i]);
147       std::string err_str;
148       TestLineCollector collector(nullptr, &std::get<1>(test),
149                                   true /* skip msg */);
150       EXPECT_FALSE(ParseSimpleStream(input, "dummy", &collector, &err_str));
151       std::string expected_err =
152           absl::StrCat("error: dummy Line ", std::get<2>(test),
153                        ", ConsumeLine failed without setting an error.");
154       EXPECT_EQ(err_str, expected_err);
155     }
156   }
157 }
158 
159 }  // namespace
160 
161 }  // namespace objectivec
162 }  // namespace compiler
163 }  // namespace protobuf
164 }  // namespace google
165