/*
* Copyright 2011 Google Inc. All Rights Reserved.
*
* 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.
*/
package com.google.devtools.j2objc.gen;
import com.google.devtools.j2objc.GenerationTest;
import com.google.devtools.j2objc.util.ErrorUtil;
import com.google.devtools.j2objc.util.NameTable;
import java.io.IOException;
/**
* Tests for {@link ObjectiveCSourceFileGenerator}.
*
* @author Tom Ball
*/
public class ObjectiveCSourceFileGeneratorTest extends GenerationTest {
public void testCamelCaseQualifiedName() {
String camelCaseName = NameTable.camelCaseQualifiedName("java.lang.Object");
assertEquals("JavaLangObject", camelCaseName);
camelCaseName = NameTable.camelCaseQualifiedName("java.util.logging.Level");
assertEquals("JavaUtilLoggingLevel", camelCaseName);
camelCaseName = NameTable.camelCaseQualifiedName("java");
assertEquals("Java", camelCaseName);
camelCaseName = NameTable.camelCaseQualifiedName("Level");
assertEquals("Level", camelCaseName);
camelCaseName = NameTable.camelCaseQualifiedName("");
assertEquals("", camelCaseName);
}
public void testCapitalize() {
assertEquals("Test", NameTable.capitalize("test"));
assertEquals("123", NameTable.capitalize("123"));
assertEquals("", NameTable.capitalize(""));
}
public void testJsniDelimiters() throws IOException {
String source =
"/*-{ jsni-comment }-*/ "
+ "class Example { "
+ " native void test1() /*-[ ocni(); ]-*/; "
+ " native void test2() /*-{ jsni(); }-*/; "
+ "}";
// First test with defaults, to see if warnings are reported.
assertTrue(options.jsniWarnings());
String translation = translateSourceFile(source, "Example", "Example.h");
assertWarningCount(2);
// Verify both methods are declared in the header. The OCNI method is
// implemented in the source. The JSNI implementation wraps an unimplemented
// function.
assertTranslation(translation, "- (void)test1;");
assertTranslation(translation, "- (void)test2;");
translation = getTranslatedFile("Example.m");
assertTranslatedLines(translation,
"- (void)test1 {",
" ocni();",
"}");
assertTranslation(translation, "void Example_test2(Example *self);");
assertTranslatedLines(translation,
"- (void)test2 {",
" Example_test2(self);",
"}");
assertNotInTranslation(translation, "jsni();");
assertNotInTranslation(translation, "jsni-comment;");
// Now rebuild with warnings disabled.
options.setJsniWarnings(false);
ErrorUtil.reset();
translation = translateSourceFile(source, "Example", "Example.h");
assertWarningCount(0);
// Verify header and source file are not affected.
assertTranslation(translation, "- (void)test1;");
assertTranslation(translation, "- (void)test2;");
translation = getTranslatedFile("Example.m");
assertTranslation(translation, "ocni();");
assertTranslation(translation, "Example_test2(self);");
assertNotInTranslation(translation, "jsni();");
assertNotInTranslation(translation, "jsni-comment;");
}
public void testStaticAccessorsAdded() throws IOException {
String header = translateSourceFile("class Test {"
+ " static int foo;"
+ " static final int finalFoo = 12;"
+ " static String bar;"
+ " static final String finalBar = \"test\";"
+ " }", "Test", "Test.h");
// finalFoo
assertTranslation(header, "#define Test_finalFoo 12");
assertTranslation(header, "jint Test_get_finalFoo();");
assertTranslation(header, "J2OBJC_STATIC_FIELD_CONSTANT(Test, finalFoo, jint)");
// foo
assertTranslation(header, "jint Test_get_foo();");
assertTranslation(header, "jint Test_set_foo(jint value);");
assertTranslation(header, "jint *Test_getRef_foo();");
assertTranslation(header, "FOUNDATION_EXPORT jint Test_foo;");
assertTranslation(header, "J2OBJC_STATIC_FIELD_PRIMITIVE(Test, foo, jint)");
// bar
assertTranslation(header, "NSString *Test_get_bar();");
assertTranslation(header, "NSString *Test_set_bar(NSString *value);");
assertTranslation(header, "FOUNDATION_EXPORT NSString *Test_bar;");
assertTranslation(header, "J2OBJC_STATIC_FIELD_OBJ(Test, bar, NSString *)");
// finalBar
assertTranslation(header, "NSString *Test_get_finalBar();");
assertTranslation(header, "FOUNDATION_EXPORT NSString *Test_finalBar;");
assertTranslation(header, "J2OBJC_STATIC_FIELD_OBJ_FINAL(Test, finalBar, NSString *)");
}
public void testPrivateStaticAccessorsAdded() throws IOException {
String translation = translateSourceFile("class Test {"
+ " private static int foo;"
+ " private static final int finalFoo = 12;"
+ " private static String bar;"
+ " private static final String finalBar = \"test\";"
+ " }", "Test", "Test.m");
assertTranslation(translation, "#define Test_finalFoo 12");
assertTranslation(translation, "J2OBJC_STATIC_FIELD_PRIMITIVE(Test, foo, jint)");
assertTranslation(translation, "J2OBJC_STATIC_FIELD_OBJ(Test, bar, NSString *)");
assertTranslation(translation, "J2OBJC_STATIC_FIELD_OBJ_FINAL(Test, finalBar, NSString *)");
}
public void testStaticReaderAddedWhenSameMethodNameExists() throws IOException {
String translation = translateSourceFile(
"class Test { static int foo; void foo(String s) {}}", "Test", "Test.h");
assertTranslation(translation, "J2OBJC_STATIC_FIELD_PRIMITIVE(Test, foo, jint)");
assertTranslation(translation, "- (void)fooWithNSString:(NSString *)s;");
}
/**
* Verify that a static reader method is not added to a class that already
* has one.
*/
public void testExistingStaticReaderDetected() throws IOException {
String translation = translateSourceFile(
"class Test { private static int foo; public static int foo() { return foo; }}", "Test",
"Test.h");
assertOccurrences(translation, "+ (jint)foo;", 1);
}
public void testTypeVariableReturnType() throws IOException {
String translation = translateSourceFile(
"interface I<T extends Runnable> { T test(); }", "Test", "Test.h");
assertTranslation(translation, "- (id<JavaLangRunnable>)test;");
}
public void testOverriddenGenericConstructor() throws IOException {
options.setDisallowInheritedConstructors(true);
addSourceFile("class A<T> { A(T t) {} }", "A.java");
String translation = translateSourceFile(
"class B extends A<String> { B(String s) { super(s); } }", "B", "B.h");
assertTranslation(translation, "- (instancetype)initWithNSString:(NSString *)s;");
assertTranslation(translation, "initWithId:(id)arg0 NS_UNAVAILABLE;");
}
public void testPrivateMethodHiding() throws IOException {
String translation = translateSourceFile(
"class Test { public void test1() {} private void test2() {} }", "Test", "Test.h");
assertTranslation(translation, "- (void)test1;");
assertNotInTranslation(translation, "test2");
translation = getTranslatedFile("Test.m");
assertTranslation(translation, "- (void)test2;"); // Private declaration, and
assertTranslation(translation, "- (void)test1 {"); // Both implementations.
assertTranslation(translation, "- (void)test2 {");
}
public void testPrivateFieldHiding() throws IOException {
String translation = translateSourceFile(
"class Test { public Object o1; protected Object o2; Object o3; private Object o4; }",
"Test", "Test.h");
assertTranslatedLines(translation, "@public", "id o1_;", "id o2_;", "id o3_;");
assertTranslation(translation, "J2OBJC_FIELD_SETTER(Test, o1_, id)");
assertTranslation(translation, "J2OBJC_FIELD_SETTER(Test, o2_, id)");
assertTranslation(translation, "J2OBJC_FIELD_SETTER(Test, o3_, id)");
assertNotInTranslation(translation, "J2OBJC_FIELD_SETTER(Test, o4_, id)");
translation = getTranslatedFile("Test.m");
assertTranslation(translation, "id o4_;");
assertTranslation(translation, "J2OBJC_FIELD_SETTER(Test, o4_, id)");
}
public void testSortingOfGenericTypes() throws IOException {
String translation = translateSourceFile(
"class Test { static class Inner1 extends Inner2<String> {} static class Inner2<T> {} }",
"Test", "Test.h");
String inner1 = "@interface Test_Inner1";
String inner2 = "@interface Test_Inner2";
assertTranslation(translation, inner1);
assertTranslation(translation, inner2);
assertTrue(translation.indexOf(inner2) < translation.indexOf(inner1));
}
}