1#!/usr/bin/env python3 2 3# Copyright 2020 The Chromium Authors 4# Use of this source code is governed by a BSD-style license that can be 5# found in the LICENSE file. 6"""Tests for java_cpp_features.py. 7 8This test suite contains various tests for the C++ -> Java base::Feature 9generator. 10""" 11 12import unittest 13 14import java_cpp_features 15from util import java_cpp_utils 16 17 18class _TestFeaturesParser(unittest.TestCase): 19 def testParseComments(self): 20 test_data = """ 21/** 22 * This should be ignored as well. 23 */ 24 25// Comment followed by a blank line. 26 27// Comment followed by unrelated code. 28int foo() { return 3; } 29 30// Real comment. base::Feature intentionally split across two lines. 31BASE_FEATURE(kSomeFeature, "SomeFeature", 32 base::FEATURE_DISABLED_BY_DEFAULT); 33 34// Real comment that spans 35// multiple lines. 36BASE_FEATURE(kSomeOtherFeature, "SomeOtherFeature", 37 base::FEATURE_ENABLED_BY_DEFAULT); 38 39// Comment followed by nothing. 40""".split('\n') 41 feature_file_parser = java_cpp_utils.CppConstantParser( 42 java_cpp_features.FeatureParserDelegate(), test_data) 43 features = feature_file_parser.Parse() 44 self.assertEqual(2, len(features)) 45 self.assertEqual('SOME_FEATURE', features[0].name) 46 self.assertEqual('"SomeFeature"', features[0].value) 47 self.assertEqual(1, len(features[0].comments.split('\n'))) 48 self.assertEqual('SOME_OTHER_FEATURE', features[1].name) 49 self.assertEqual('"SomeOtherFeature"', features[1].value) 50 self.assertEqual(2, len(features[1].comments.split('\n'))) 51 52 def testWhitespace(self): 53 test_data = """ 54// 1 line 55BASE_FEATURE(kShort, "Short", base::FEATURE_DISABLED_BY_DEFAULT); 56 57// 2 lines 58BASE_FEATURE(kTwoLineFeatureA, "TwoLineFeatureA", 59 base::FEATURE_DISABLED_BY_DEFAULT); 60BASE_FEATURE(kTwoLineFeatureB, 61 "TwoLineFeatureB", base::FEATURE_DISABLED_BY_DEFAULT); 62 63// 3 lines 64BASE_FEATURE(kFeatureWithAVeryLongNameThatWillHaveToWrap, 65 "FeatureWithAVeryLongNameThatWillHaveToWrap", 66 base::FEATURE_DISABLED_BY_DEFAULT); 67""".split('\n') 68 feature_file_parser = java_cpp_utils.CppConstantParser( 69 java_cpp_features.FeatureParserDelegate(), test_data) 70 features = feature_file_parser.Parse() 71 self.assertEqual(4, len(features)) 72 self.assertEqual('SHORT', features[0].name) 73 self.assertEqual('"Short"', features[0].value) 74 self.assertEqual('TWO_LINE_FEATURE_A', features[1].name) 75 self.assertEqual('"TwoLineFeatureA"', features[1].value) 76 self.assertEqual('TWO_LINE_FEATURE_B', features[2].name) 77 self.assertEqual('"TwoLineFeatureB"', features[2].value) 78 self.assertEqual('FEATURE_WITH_A_VERY_LONG_NAME_THAT_WILL_HAVE_TO_WRAP', 79 features[3].name) 80 self.assertEqual('"FeatureWithAVeryLongNameThatWillHaveToWrap"', 81 features[3].value) 82 83 def testCppSyntax(self): 84 test_data = """ 85// Mismatched name 86BASE_FEATURE(kMismatchedFeature, "MismatchedName", 87 base::FEATURE_DISABLED_BY_DEFAULT); 88 89namespace myfeature { 90// In a namespace 91BASE_FEATURE(kSomeFeature, "SomeFeature", 92 base::FEATURE_DISABLED_BY_DEFAULT); 93} 94 95// Build config-specific base::Feature 96#if BUILDFLAG(IS_ANDROID) 97BASE_FEATURE(kAndroidOnlyFeature, "AndroidOnlyFeature", 98 base::FEATURE_DISABLED_BY_DEFAULT); 99#endif 100 101// Value depends on build config 102BASE_FEATURE(kMaybeEnabled, "MaybeEnabled", 103#if BUILDFLAG(IS_ANDROID) 104 base::FEATURE_DISABLED_BY_DEFAULT 105#else 106 base::FEATURE_ENABLED_BY_DEFAULT 107#endif 108); 109""".split('\n') 110 feature_file_parser = java_cpp_utils.CppConstantParser( 111 java_cpp_features.FeatureParserDelegate(), test_data) 112 features = feature_file_parser.Parse() 113 self.assertEqual(4, len(features)) 114 self.assertEqual('MISMATCHED_FEATURE', features[0].name) 115 self.assertEqual('"MismatchedName"', features[0].value) 116 self.assertEqual('SOME_FEATURE', features[1].name) 117 self.assertEqual('"SomeFeature"', features[1].value) 118 self.assertEqual('ANDROID_ONLY_FEATURE', features[2].name) 119 self.assertEqual('"AndroidOnlyFeature"', features[2].value) 120 self.assertEqual('MAYBE_ENABLED', features[3].name) 121 self.assertEqual('"MaybeEnabled"', features[3].value) 122 123 def testNotYetSupported(self): 124 # Negative test for cases we don't yet support, to ensure we don't misparse 125 # these until we intentionally add proper support. 126 test_data = """ 127// Not currently supported: name depends on C++ directive 128BASE_FEATURE(kNameDependsOnOs, 129#if BUILDFLAG(IS_ANDROID) 130 "MaybeName1", 131#else 132 "MaybeName2", 133#endif 134 base::FEATURE_DISABLED_BY_DEFAULT); 135 136// Not currently supported: feature named with a constant instead of literal 137BASE_FEATURE(kNamedAfterConstant, kNamedStringConstant, 138 base::FEATURE_DISABLED_BY_DEFAULT}; 139""".split('\n') 140 feature_file_parser = java_cpp_utils.CppConstantParser( 141 java_cpp_features.FeatureParserDelegate(), test_data) 142 features = feature_file_parser.Parse() 143 self.assertEqual(0, len(features)) 144 145 def testTreatWebViewLikeOneWord(self): 146 test_data = """ 147BASE_FEATURE(kSomeWebViewFeature, "SomeWebViewFeature", 148 base::FEATURE_DISABLED_BY_DEFAULT); 149BASE_FEATURE(kWebViewOtherFeature, "WebViewOtherFeature", 150 base::FEATURE_ENABLED_BY_DEFAULT); 151BASE_FEATURE(kFeatureWithPluralWebViews, 152 "FeatureWithPluralWebViews", 153 base::FEATURE_ENABLED_BY_DEFAULT); 154""".split('\n') 155 feature_file_parser = java_cpp_utils.CppConstantParser( 156 java_cpp_features.FeatureParserDelegate(), test_data) 157 features = feature_file_parser.Parse() 158 self.assertEqual('SOME_WEBVIEW_FEATURE', features[0].name) 159 self.assertEqual('"SomeWebViewFeature"', features[0].value) 160 self.assertEqual('WEBVIEW_OTHER_FEATURE', features[1].name) 161 self.assertEqual('"WebViewOtherFeature"', features[1].value) 162 self.assertEqual('FEATURE_WITH_PLURAL_WEBVIEWS', features[2].name) 163 self.assertEqual('"FeatureWithPluralWebViews"', features[2].value) 164 165 def testSpecialCharacters(self): 166 test_data = r""" 167BASE_FEATURE(kFeatureWithEscapes, "Weird\tfeature\"name\n", 168 base::FEATURE_DISABLED_BY_DEFAULT); 169BASE_FEATURE(kFeatureWithEscapes2, 170 "Weird\tfeature\"name\n", 171 base::FEATURE_ENABLED_BY_DEFAULT); 172""".split('\n') 173 feature_file_parser = java_cpp_utils.CppConstantParser( 174 java_cpp_features.FeatureParserDelegate(), test_data) 175 features = feature_file_parser.Parse() 176 self.assertEqual('FEATURE_WITH_ESCAPES', features[0].name) 177 self.assertEqual(r'"Weird\tfeature\"name\n"', features[0].value) 178 self.assertEqual('FEATURE_WITH_ESCAPES2', features[1].name) 179 self.assertEqual(r'"Weird\tfeature\"name\n"', features[1].value) 180 181 182if __name__ == '__main__': 183 unittest.main() 184