• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /* Copyright 2017 The TensorFlow Authors. All Rights Reserved.
2 
3 Licensed under the Apache License, Version 2.0 (the "License");
4 you may not use this file except in compliance with the License.
5 You may obtain a copy of the License at
6 
7     http://www.apache.org/licenses/LICENSE-2.0
8 
9 Unless required by applicable law or agreed to in writing, software
10 distributed under the License is distributed on an "AS IS" BASIS,
11 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 See the License for the specific language governing permissions and
13 limitations under the License.
14 ==============================================================================*/
15 
16 #include <list>
17 
18 #include "tensorflow/core/lib/io/path.h"
19 #include "tensorflow/core/platform/test.h"
20 #include "tensorflow/java/src/gen/cc/java_defs.h"
21 #include "tensorflow/java/src/gen/cc/source_writer.h"
22 
23 namespace tensorflow {
24 namespace java {
25 namespace {
26 
TEST(AppendTest,SingleLineText)27 TEST(AppendTest, SingleLineText) {
28   SourceBufferWriter writer;
29   writer.Append("You say goodbye and I say hello!");
30 
31   const char* expected = "You say goodbye and I say hello!";
32   ASSERT_STREQ(expected, writer.str().data());
33 }
34 
TEST(AppendTest,MultiLineText)35 TEST(AppendTest, MultiLineText) {
36   SourceBufferWriter writer;
37   writer.Append("You say goodbye\nand I say hello!");
38 
39   const char* expected = "You say goodbye\nand I say hello!";
40   ASSERT_STREQ(expected, writer.str().data());
41 }
42 
TEST(AppendTest,MultiLineTextWithIndent)43 TEST(AppendTest, MultiLineTextWithIndent) {
44   SourceBufferWriter writer;
45   writer.Indent(2).Append("You say goodbye\nand I say hello!");
46 
47   const char* expected = "  You say goodbye\nand I say hello!";
48   ASSERT_STREQ(expected, writer.str().data());
49 }
50 
TEST(AppendTest,MultiLineTextWithPrefix)51 TEST(AppendTest, MultiLineTextWithPrefix) {
52   SourceBufferWriter writer;
53   writer.Prefix("--").Append("You say goodbye\nand I say hello!");
54 
55   const char* expected = "--You say goodbye\nand I say hello!";
56   ASSERT_STREQ(expected, writer.str().data());
57 }
58 
TEST(AppendTest,MultiLineTextWithIndentAndPrefix)59 TEST(AppendTest, MultiLineTextWithIndentAndPrefix) {
60   SourceBufferWriter writer;
61   writer.Indent(2).Prefix("--").Append("You say goodbye\nand I say hello!");
62 
63   const char* expected = "  --You say goodbye\nand I say hello!";
64   ASSERT_STREQ(expected, writer.str().data());
65 }
66 
TEST(WriteTest,SingleLineText)67 TEST(WriteTest, SingleLineText) {
68   SourceBufferWriter writer;
69   writer.Write("You say goodbye and I say hello!");
70 
71   const char* expected = "You say goodbye and I say hello!";
72   ASSERT_STREQ(expected, writer.str().data());
73 }
74 
TEST(WriteTest,MultiLineText)75 TEST(WriteTest, MultiLineText) {
76   SourceBufferWriter writer;
77   writer.Write("You say goodbye\nand I say hello!");
78 
79   const char* expected = "You say goodbye\nand I say hello!";
80   ASSERT_STREQ(expected, writer.str().data());
81 }
82 
TEST(WriteTest,MultiLineTextWithIndent)83 TEST(WriteTest, MultiLineTextWithIndent) {
84   SourceBufferWriter writer;
85   writer.Indent(2).Write("You say goodbye\nand I say hello!");
86 
87   const char* expected = "  You say goodbye\n  and I say hello!";
88   ASSERT_STREQ(expected, writer.str().data());
89 }
90 
TEST(WriteTest,MultiLineTextWithPrefix)91 TEST(WriteTest, MultiLineTextWithPrefix) {
92   SourceBufferWriter writer;
93   writer.Prefix("--").Write("You say goodbye\nand I say hello!");
94 
95   const char* expected = "--You say goodbye\n--and I say hello!";
96   ASSERT_STREQ(expected, writer.str().data());
97 }
98 
TEST(WriteTest,MultiLineTextWithIndentAndPrefix)99 TEST(WriteTest, MultiLineTextWithIndentAndPrefix) {
100   SourceBufferWriter writer;
101   writer.Indent(2).Prefix("--").Write("You say goodbye\nand I say hello!");
102 
103   const char* expected = "  --You say goodbye\n  --and I say hello!";
104   ASSERT_STREQ(expected, writer.str().data());
105 }
106 
TEST(MarginTest,Basic)107 TEST(MarginTest, Basic) {
108   SourceBufferWriter writer;
109   writer.Append("You say goodbye").EndLine().Append("and I say hello!");
110 
111   const char* expected = "You say goodbye\nand I say hello!";
112   ASSERT_STREQ(expected, writer.str().data());
113 }
114 
TEST(MarginTest,Indent)115 TEST(MarginTest, Indent) {
116   SourceBufferWriter writer;
117   writer.Append("You say goodbye")
118       .EndLine()
119       .Indent(2)
120       .Append("and I say hello!");
121 
122   const char* expected = "You say goodbye\n  and I say hello!";
123   ASSERT_STREQ(expected, writer.str().data());
124 }
125 
TEST(MarginTest,IndentAndOutdent)126 TEST(MarginTest, IndentAndOutdent) {
127   SourceBufferWriter writer;
128   writer.Append("You say goodbye")
129       .EndLine()
130       .Indent(2)
131       .Append("and I say hello!")
132       .EndLine()
133       .Indent(-2)
134       .Append("Hello, hello!");
135 
136   const char* expected = "You say goodbye\n  and I say hello!\nHello, hello!";
137   ASSERT_STREQ(expected, writer.str().data());
138 }
139 
TEST(MarginTest,Prefix)140 TEST(MarginTest, Prefix) {
141   SourceBufferWriter writer;
142   writer.Append("You say goodbye")
143       .EndLine()
144       .Prefix("--")
145       .Append("and I say hello!");
146 
147   const char* expected = "You say goodbye\n--and I say hello!";
148   ASSERT_STREQ(expected, writer.str().data());
149 }
150 
TEST(MarginTest,PrefixAndRemovePrefix)151 TEST(MarginTest, PrefixAndRemovePrefix) {
152   SourceBufferWriter writer;
153   writer.Append("You say goodbye")
154       .EndLine()
155       .Prefix("--")
156       .Append("and I say hello!")
157       .EndLine()
158       .Prefix("")
159       .Append("Hello, hello!");
160 
161   const char* expected = "You say goodbye\n--and I say hello!\nHello, hello!";
162   ASSERT_STREQ(expected, writer.str().data());
163 }
164 
TEST(MarginTest,IndentAndPrefixAndOutdentAndRemovePrefix)165 TEST(MarginTest, IndentAndPrefixAndOutdentAndRemovePrefix) {
166   SourceBufferWriter writer;
167   writer.Append("You say goodbye")
168       .EndLine()
169       .Indent(2)
170       .Prefix("--")
171       .Append("and I say hello!")
172       .EndLine()
173       .Indent(-2)
174       .Prefix("")
175       .Append("Hello, hello!");
176 
177   const char* expected = "You say goodbye\n  --and I say hello!\nHello, hello!";
178   ASSERT_STREQ(expected, writer.str().data());
179 }
180 
TEST(MarginTest,NegativeIndent)181 TEST(MarginTest, NegativeIndent) {
182   SourceBufferWriter writer;
183   writer.Append("You say goodbye")
184       .EndLine()
185       .Indent(-10)
186       .Append("and I say hello!");
187 
188   const char* expected = "You say goodbye\nand I say hello!";
189   ASSERT_STREQ(expected, writer.str().data());
190 }
191 
TEST(MarginTest,CumulativeIndent)192 TEST(MarginTest, CumulativeIndent) {
193   SourceBufferWriter writer;
194   writer.Append("You say goodbye")
195       .EndLine()
196       .Indent(2)
197       .Append("and I say hello!")
198       .EndLine()
199       .Indent(2)
200       .Append("Hello, hello!");
201 
202   const char* expected =
203       "You say goodbye\n  and I say hello!\n    Hello, hello!";
204   ASSERT_STREQ(expected, writer.str().data());
205 }
206 
TEST(MarginTest,EmptyPrefix)207 TEST(MarginTest, EmptyPrefix) {
208   SourceBufferWriter writer;
209   writer.Append("You say goodbye")
210       .EndLine()
211       .Prefix("")
212       .Append("and I say hello!");
213 
214   const char* expected = "You say goodbye\nand I say hello!";
215   ASSERT_STREQ(expected, writer.str().data());
216 }
217 
TEST(StreamTest,BlocksAndLines)218 TEST(StreamTest, BlocksAndLines) {
219   SourceBufferWriter writer;
220 
221   writer.Append("int i = 0;").EndLine()
222         .Append("int j = 10;").EndLine()
223         .Append("if (true)")
224         .BeginBlock()
225           .Append("int aLongWayToTen = 0;").EndLine()
226           .Append("while (++i <= j)")
227           .BeginBlock()
228             .Append("++aLongWayToTen;").EndLine()
229           .EndBlock()
230         .EndBlock();
231 
232   const char* expected =
233       "int i = 0;\n"
234       "int j = 10;\n"
235       "if (true) {\n"
236       "  int aLongWayToTen = 0;\n"
237       "  while (++i <= j) {\n"
238       "    ++aLongWayToTen;\n"
239       "  }\n"
240       "}\n";
241   ASSERT_STREQ(expected, writer.str().data());
242 }
243 
TEST(StreamTest,Types)244 TEST(StreamTest, Types) {
245   SourceBufferWriter writer;
246   Type generic = Type::Generic("T").add_supertype(Type::Class("Number"));
247 
248   writer.AppendType(Type::Int())
249       .Append(", ")
250       .AppendType(Type::Class("String"))
251       .Append(", ")
252       .AppendType(generic)
253       .Append(", ")
254       .AppendType(Type::ListOf(generic))
255       .Append(", ")
256       .AppendType(Type::ListOf(Type::IterableOf(generic)))
257       .Append(", ")
258       .AppendType(Type::ListOf(Type::Wildcard()));
259 
260   const char* expected =
261       "int, String, T, List<T>, List<Iterable<T>>, List<?>";
262   ASSERT_STREQ(expected, writer.str().data());
263 }
264 
TEST(StreamTest,FileSnippet)265 TEST(StreamTest, FileSnippet) {
266   SourceBufferWriter writer;
267   const string fname = tensorflow::io::JoinPath(
268       tensorflow::testing::TensorFlowSrcRoot(),
269       "java/src/gen/resources/test.java.snippet");
270 
271   writer.WriteFromFile(fname)
272         .BeginBlock()
273         .WriteFromFile(fname)
274         .EndBlock();
275 
276   const char* expected =
277       "// Here is a little snippet\n"
278       "System.out.println(\"Hello!\");\n"
279       "{\n"
280       "  // Here is a little snippet\n"
281       "  System.out.println(\"Hello!\");\n"
282       "}\n";
283   ASSERT_STREQ(expected, writer.str().data());
284 }
285 
TEST(WriteType,SimpleClass)286 TEST(WriteType, SimpleClass) {
287   SourceBufferWriter writer;
288   Type clazz = Type::Class("Test", "org.tensorflow");
289 
290   writer.BeginType(clazz, PUBLIC).EndType();
291 
292   const char* expected =
293       "package org.tensorflow;\n\n"
294       "public class Test {\n}\n";
295   ASSERT_STREQ(expected, writer.str().data());
296 }
297 
TEST(WriteType,SimpleClassWithDependencies)298 TEST(WriteType, SimpleClassWithDependencies) {
299   SourceBufferWriter writer;
300   Type clazz = Type::Class("Test", "org.tensorflow");
301   std::list<Type> deps;
302   deps.push_back(Type::Class("TypeA", "org.test.sub"));
303   deps.push_back(Type::Class("TypeA", "org.test.sub"));  // a second time
304   deps.push_back(Type::Class("TypeB", "org.other"));
305   deps.push_back(Type::Class("SamePackageType", "org.tensorflow"));
306   deps.push_back(Type::Class("NoPackageType"));
307 
308   writer.BeginType(clazz, PUBLIC, &deps).EndType();
309 
310   const char* expected =
311       "package org.tensorflow;\n\n"
312       "import org.other.TypeB;\n"
313       "import org.test.sub.TypeA;\n\n"
314       "public class Test {\n}\n";
315   ASSERT_STREQ(expected, writer.str().data());
316 }
317 
TEST(WriteType,AnnotatedAndDocumentedClass)318 TEST(WriteType, AnnotatedAndDocumentedClass) {
319   SourceBufferWriter writer;
320   Type clazz = Type::Class("Test", "org.tensorflow");
321   Javadoc clazz_doc = Javadoc::Create("Javadoc test")
322                           .details("This is a\nmultiline description.");
323   clazz.add_annotation(Annotation::Create("Bean"));
324   clazz.add_annotation(Annotation::Create("SuppressWarnings")
325       .attributes("\"rawtypes\""));
326 
327   writer.BeginType(clazz, PUBLIC, nullptr, &clazz_doc).EndType();
328 
329   const char* expected =
330       "package org.tensorflow;\n\n"
331       "/**\n"
332       " * Javadoc test\n"
333       " * <p>\n"
334       " * This is a\n"
335       " * multiline description.\n"
336       " */\n"
337       "@Bean\n"
338       "@SuppressWarnings(\"rawtypes\")\n"
339       "public class Test {\n}\n";
340   ASSERT_STREQ(expected, writer.str().data());
341 }
342 
TEST(WriteType,ParameterizedClass)343 TEST(WriteType, ParameterizedClass) {
344   SourceBufferWriter writer;
345   Type clazz = Type::Class("Test", "org.tensorflow");
346   clazz.add_parameter(Type::Generic("T"));
347   clazz.add_parameter(Type::Generic("U").add_supertype(Type::Class("Number")));
348 
349   writer.BeginType(clazz, PUBLIC).EndType();
350 
351   const char* expected =
352       "package org.tensorflow;\n\n"
353       "public class Test<T, U extends Number> {\n}\n";
354   ASSERT_STREQ(expected, writer.str().data());
355 }
356 
TEST(WriteType,ParameterizedClassAndSupertypes)357 TEST(WriteType, ParameterizedClassAndSupertypes) {
358   SourceBufferWriter writer;
359   Type clazz = Type::Class("Test", "org.tensorflow");
360   Type type_t = Type::Generic("T");
361   clazz.add_parameter(type_t);
362   Type type_u = Type::Generic("U").add_supertype(Type::Class("Number"));
363   clazz.add_parameter(type_u);
364   clazz.add_supertype(Type::Interface("Parameterizable").add_parameter(type_u));
365   clazz.add_supertype(Type::Interface("Runnable"));
366   clazz.add_supertype(Type::Class("SuperTest").add_parameter(type_t));
367 
368   writer.BeginType(clazz, PUBLIC).EndType();
369 
370   const char* expected =
371       "package org.tensorflow;\n\n"
372       "public class Test<T, U extends Number>"
373       " extends SuperTest<T> implements Parameterizable<U>, Runnable {\n}\n";
374   ASSERT_STREQ(expected, writer.str().data());
375 }
376 
TEST(WriteType,ParameterizedClassFields)377 TEST(WriteType, ParameterizedClassFields) {
378   SourceBufferWriter writer;
379   Type clazz = Type::Class("Test", "org.tensorflow");
380   Type type_t = Type::Generic("T").add_supertype(Type::Class("Number"));
381   clazz.add_parameter(type_t);
382   Variable field1 = Variable::Create("field1", Type::Class("String"));
383   Variable field2 = Variable::Create("field2", Type::Class("String"));
384   Variable field3 = Variable::Create("field3", type_t);
385   Javadoc field3_doc = Javadoc::Create("This variable is documented");
386 
387   writer.BeginType(clazz, PUBLIC)
388       .WriteField(field1, STATIC | PUBLIC | FINAL)
389       .WriteField(field2, PRIVATE)
390       .WriteField(field3, PRIVATE, &field3_doc)
391       .EndType();
392 
393   const char* expected =
394       "package org.tensorflow;\n\n"
395       "public class Test<T extends Number> {\n"
396       "  public static final String field1;\n"
397       "  private String field2;\n"
398       "  /** This variable is documented */\n"
399       "  private T field3;\n"
400       "}\n";
401   ASSERT_STREQ(expected, writer.str().data());
402 }
403 
TEST(WriteType,SimpleInnerClass)404 TEST(WriteType, SimpleInnerClass) {
405   SourceBufferWriter writer;
406   Type clazz = Type::Class("Test", "org.tensorflow");
407   Type inner_class = Type::Class("InnerTest");
408 
409   writer.BeginType(clazz, PUBLIC)
410       .BeginInnerType(inner_class, PUBLIC)
411       .EndType()
412       .EndType();
413 
414   const char* expected =
415       "package org.tensorflow;\n\n"
416       "public class Test {\n"
417       "  \n"
418       "  public class InnerTest {\n"
419       "  }\n"
420       "}\n";
421   ASSERT_STREQ(expected, writer.str().data());
422 }
423 
TEST(WriteType,StaticParameterizedInnerClass)424 TEST(WriteType, StaticParameterizedInnerClass) {
425   SourceBufferWriter writer;
426   Type clazz = Type::Class("Test", "org.tensorflow");
427   Type type_t = Type::Generic("T").add_supertype(Type::Class("Number"));
428   clazz.add_parameter(type_t);
429   Type inner_class = Type::Class("InnerTest");
430   inner_class.add_parameter(type_t);
431 
432   writer.BeginType(clazz, PUBLIC)
433       .BeginInnerType(inner_class, PUBLIC | STATIC)
434       .EndType()
435       .EndType();
436 
437   const char* expected =
438       "package org.tensorflow;\n\n"
439       "public class Test<T extends Number> {\n"
440       "  \n"
441       "  public static class InnerTest<T extends Number> {\n"
442       "  }\n"
443       "}\n";
444   ASSERT_STREQ(expected, writer.str().data());
445 }
446 
TEST(WriteMethod,SimpleMethod)447 TEST(WriteMethod, SimpleMethod) {
448   SourceBufferWriter writer;
449   Type clazz = Type::Class("Test", "org.tensorflow");
450   Method method = Method::Create("doNothing", Type::Void());
451 
452   writer.BeginType(clazz, PUBLIC)
453       .BeginMethod(method, PUBLIC)
454       .EndMethod()
455       .EndType();
456 
457   const char* expected =
458       "package org.tensorflow;\n\n"
459       "public class Test {\n"
460       "  \n"
461       "  public void doNothing() {\n"
462       "  }\n"
463       "}\n";
464   ASSERT_STREQ(expected, writer.str().data());
465 }
466 
TEST(WriteMethod,AnnotatedAndDocumentedMethod)467 TEST(WriteMethod, AnnotatedAndDocumentedMethod) {
468   SourceBufferWriter writer;
469   Type clazz = Type::Class("Test", "org.tensorflow");
470   Method method = Method::Create("doNothing", Type::Void());
471   Javadoc method_doc =
472       Javadoc::Create("Javadoc test")
473           .details("This method has a\nmultiline description.");
474   method.add_annotation(Annotation::Create("Override"));
475   method.add_annotation(Annotation::Create("SuppressWarnings")
476       .attributes("\"rawtypes\""));
477 
478   writer.BeginType(clazz, PUBLIC)
479       .BeginMethod(method, PUBLIC, &method_doc)
480       .EndMethod()
481       .EndType();
482 
483   const char* expected =
484       "package org.tensorflow;\n\n"
485       "public class Test {\n"
486       "  \n"
487       "  /**\n"
488       "   * Javadoc test\n"
489       "   * <p>\n"
490       "   * This method has a\n"
491       "   * multiline description.\n"
492       "   */\n"
493       "  @Override\n"
494       "  @SuppressWarnings(\"rawtypes\")\n"
495       "  public void doNothing() {\n"
496       "  }\n"
497       "}\n";
498   ASSERT_STREQ(expected, writer.str().data());
499 }
500 
TEST(WriteMethod,DocumentedMethodWithArguments)501 TEST(WriteMethod, DocumentedMethodWithArguments) {
502   SourceBufferWriter writer;
503   Type clazz = Type::Class("Test", "org.tensorflow");
504   Variable reverse = Variable::Create("reverse", Type::Boolean());
505   Method method = Method::Create("boolToInt", Type::Int());
506   method.add_argument(Variable::Create("b", Type::Boolean()));
507   method.add_argument(reverse);
508   Javadoc method_doc =
509       Javadoc::Create("Converts a boolean to an int")
510           .details("This method will convert\na boolean to an int")
511           .add_param_tag(reverse.name(), "if true, value is reversed")
512           .add_tag("return", "int value for this boolean");
513 
514   writer.BeginType(clazz, PUBLIC)
515       .BeginMethod(method, PUBLIC, &method_doc)
516       .Append("if (b && !reverse)")
517       .BeginBlock()
518       .Append("return 1;")
519       .EndLine()
520       .EndBlock()
521       .Append("return 0;")
522       .EndLine()
523       .EndMethod()
524       .EndType();
525 
526   const char* expected =
527       "package org.tensorflow;\n\n"
528       "public class Test {\n"
529       "  \n"
530       "  /**\n"
531       "   * Converts a boolean to an int\n"
532       "   * <p>\n"
533       "   * This method will convert\n"
534       "   * a boolean to an int\n"
535       "   * \n"
536       "   * @param reverse if true, value is reversed\n"
537       "   * @return int value for this boolean\n"
538       "   */\n"
539       "  public int boolToInt(boolean b, boolean reverse) {\n"
540       "    if (b && !reverse) {\n"
541       "      return 1;\n"
542       "    }\n"
543       "    return 0;\n"
544       "  }\n"
545       "}\n";
546   ASSERT_STREQ(expected, writer.str().data());
547 }
548 
TEST(WriteMethod,ParameterizedMethod)549 TEST(WriteMethod, ParameterizedMethod) {
550   SourceBufferWriter writer;
551   Type clazz = Type::Class("Test", "org.tensorflow");
552   Type type_t = Type::Generic("T").add_supertype(Type::Class("Number"));
553   clazz.add_parameter(type_t);
554   Method method = Method::Create("doNothing", type_t);
555 
556   writer.BeginType(clazz, PUBLIC)
557       .BeginMethod(method, PUBLIC)
558       .Append("return null;")
559       .EndLine()
560       .EndMethod()
561       .EndType();
562 
563   const char* expected =
564       "package org.tensorflow;\n\n"
565       "public class Test<T extends Number> {\n"
566       "  \n"
567       "  public T doNothing() {\n"
568       "    return null;\n"
569       "  }\n"
570       "}\n";
571   ASSERT_STREQ(expected, writer.str().data());
572 }
573 
TEST(WriteMethod,StaticParameterizedMethod)574 TEST(WriteMethod, StaticParameterizedMethod) {
575   SourceBufferWriter writer;
576   Type clazz = Type::Class("Test", "org.tensorflow");
577   Type type_t = Type::Generic("T").add_supertype(Type::Class("Number"));
578   clazz.add_parameter(type_t);
579   Method method = Method::Create("doNothing", type_t);
580 
581   writer.BeginType(clazz, PUBLIC)
582       .BeginMethod(method, PUBLIC | STATIC)
583       .Append("return null;")
584       .EndLine()
585       .EndMethod()
586       .EndType();
587 
588   const char* expected =
589       "package org.tensorflow;\n\n"
590       "public class Test<T extends Number> {\n"
591       "  \n"
592       "  public static <T extends Number> T doNothing() {\n"
593       "    return null;\n"
594       "  }\n"
595       "}\n";
596   ASSERT_STREQ(expected, writer.str().data());
597 }
598 
599 }  // namespace
600 }  // namespace java
601 }  // namespace tensorflow
602