-
Notifications
You must be signed in to change notification settings - Fork 499
/
RegexPatternValidationCheckTest.kt
2789 lines (2417 loc) · 116 KB
/
RegexPatternValidationCheckTest.kt
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
package org.oppia.android.scripts.regex
import com.google.common.truth.Truth.assertThat
import org.junit.After
import org.junit.Before
import org.junit.Rule
import org.junit.Test
import org.junit.rules.TemporaryFolder
import org.oppia.android.testing.assertThrows
import java.io.ByteArrayOutputStream
import java.io.File
import java.io.PrintStream
/** Tests for the regex pattern validation check (see [main]). */
// FunctionName: test names are conventionally named with underscores.
@Suppress("FunctionName")
class RegexPatternValidationCheckTest {
private val outContent: ByteArrayOutputStream = ByteArrayOutputStream()
private val originalOut: PrintStream = System.out
private val activitiesPlacementErrorMessage =
"Activities cannot be placed outside the app or testing module."
private val nestedResourceSubdirectoryErrorMessage =
"Only one level of subdirectories under res/ should be maintained (further subdirectories " +
"aren't supported by the project configuration)."
private val supportLibraryUsageErrorMessage =
"AndroidX should be used instead of the support library"
private val coroutineWorkerUsageErrorMessage =
"For stable tests, prefer using ListenableWorker with an Oppia-managed dispatcher."
private val announceForAccessibilityUsageErrorMessage =
"Please use AccessibilityService instead."
private val announceForAccessibilityForViewUsageErrorMessage =
"When using announceForAccessibility, please add an exempt file in " +
"file_content_validation_checks.textproto."
private val settableFutureUsageErrorMessage =
"SettableFuture should only be used in pre-approved locations since it's easy to potentially " +
"mess up & lead to a hanging ListenableFuture."
private val androidLayoutIncludeTagErrorMessage =
"Remove <include .../> tag from layouts and instead use the widget directly, e.g. AppBarLayout."
private val androidGravityLeftErrorMessage =
"Use android:gravity=\"start\", instead, for proper RTL support"
private val androidGravityRightErrorMessage =
"Use android:gravity=\"end\", instead, for proper RTL support"
private val androidLayoutGravityLeftErrorMessage =
"Use android:layout_gravity=\"start\", instead, for proper RTL support"
private val androidLayoutGravityRightErrorMessage =
"Use android:layout_gravity=\"end\", instead, for proper RTL support"
private val androidGenericStartEndRtlErrorMessage =
"Use start/end versions of layout properties, instead, for proper RTL support"
private val androidBarrierDirectionLeftErrorMessage =
"Use app:barrierDirection=\"start\", instead, for proper RTL support"
private val androidBarrierDirectionRightErrorMessage =
"Use app:barrierDirection=\"end\", instead, for proper RTL support"
private val androidDragDirectionLeftErrorMessage =
"Use motion:dragDirection=\"start\", instead, for proper RTL support"
private val androidDragDirectionRightErrorMessage =
"Use motion:dragDirection=\"end\", instead, for proper RTL support"
private val androidTouchAnchorSideLeftErrorMessage =
"Use motion:touchAnchorSide=\"start\", instead, for proper RTL support"
private val androidTouchAnchorSideRightErrorMessage =
"Use motion:touchAnchorSide=\"end\", instead, for proper RTL support"
private val oppiaCantBeTranslatedErrorMessage =
"Oppia should never used directly in a string (since it shouldn't be translated). Instead, " +
"use a parameter & insert the string retrieved from app_name."
private val untranslatableStringsGoInSpecificFileErrorMessage =
"Untranslatable strings should go in untranslated_strings.xml, instead."
private val translatableStringsGoInMainFileErrorMessage =
"All strings outside strings.xml must be marked as not translatable, or moved to strings.xml."
private val translatablePluralsGoInMainFileErrorMessage =
"All plurals outside strings.xml must be marked as not translatable, or moved to strings.xml."
private val importingAndroidBidiFormatterErrorMessage =
"Do not use Android's BidiFormatter directly. Instead, use AndroidX's BidiFormatter for" +
" KitKat compatibility."
private val importingAndroidXBidiFormatterErrorMessage =
"Do not use AndroidX's BidiFormatter directly. Instead, use the wrapper utility" +
" OppiaBidiFormatter so that tests can verify that formatting actually occurs on select" +
" strings."
private val useStringFormattingFunctionInKotlinOrJavaErrorMessage =
"String formatting and resource retrieval should go through AppLanguageResourceHandler," +
" OppiaLocale.DisplayLocale, or OppiaLocale.MachineLocale depending on the context (see" +
" each class's documentation for details on when each should be used)."
private val useCaseInsensitiveOperationErrorMessage =
"Case-insensitive string operations should be performed using MachineLocale."
private val useStringFormattingFunctionInXmlErrorMessage =
"String formatting and resource retrieval in layouts should go through" +
" AppLanguageResourceHandler."
private val useDatabindingStringOperationsErrorMessage =
"String formatting and quantity string building shouldn't be done directly through" +
" databinding. Instead, pass in AppLanguageResourceHandler from the view model or call a" +
" new function through the view model to compute the string. Both should use the handler's" +
" locale-safe formatting/quantity string methods."
private val useDatabindingPluralsErrorMessage =
"String plurals shouldn't be constructed directly through databinding. Instead, pass in" +
" AppLanguageResourceHandler from the view model or call a new function through the view" +
" model to compute the string. Both should use the handler's locale-safe" +
" formatting/quantity string methods."
private val useNonStringTypeSpecifiersErrorMessage =
"Only string type specifiers should use for strings (to avoid runtime errors due to" +
" bidirectional wrapping requirements)."
private val subclassedActivityErrorMessage =
"Activity should never be subclassed. Use AppCompatActivity, instead."
private val subclassedAppCompatActivityErrorMessage =
"Never subclass AppCompatActivity directly. Instead, use InjectableAppCompatActivity."
private val subclassedInjectableAppCompatActivityErrorMessage =
"Never subclass InjectableAppCompatActivity directly. Instead, use " +
"InjectableSystemLocalizedAppCompatActivity or InjectableAutoLocalizedAppCompatActivity."
private val subclassedDialogFragmentErrorMessage =
"DialogFragment should never be subclassed. Use InjectableDialogFragment, instead."
private val androidActivityConfigChangesErrorMessage =
"Never explicitly handle configuration changes. Instead, use saved instance states for" +
" retaining state across rotations. For other types of configuration changes, follow up" +
" with the developer mailing list with how to proceed if you think this is a legitimate case."
private val androidManifestFirebaseAnalyticsEnabledErrorMessage =
"Firebase analytics collection should always be explicitly deactivated in develop."
private val androidManifestFirebaseCrashlyticsEnabledErrorMessage =
"Firebase crashlytics collection should always be explicitly deactivated in develop."
private val nonCompatDrawableUsedErrorMessage =
"Drawable start/end/top/bottom & image source should use the compat versions, instead, e.g.:" +
" app:drawableStartCompat or app:srcCompat, to ensure that vector drawables can load" +
" properly in SDK <21 environments."
private val useJava8OptionalErrorMessage =
"Prefer using com.google.common.base.Optional (Guava's Optional) since desugaring has some" +
" incompatibilities between Bazel & KitKat builds."
private val useJavaCalendarErrorMessage =
"Don't use Calendar directly. Instead, use OppiaClock and/or OppiaLocale for" +
" calendar-specific operations."
private val useJavaDateErrorMessage =
"Don't use Date directly. Instead, perform date-based operations using OppiaLocale."
private val useJavaTextErrorMessage =
"Don't perform date/time formatting directly. Instead, use OppiaLocale."
private val useJavaLocaleErrorMessage =
"Don't use Locale directly. Instead, use LocaleController, or OppiaLocale & its subclasses."
private val doNotUseKotlinDelegatesErrorMessage =
"Don't use Delegates; use a lateinit var or nullable primitive var default-initialized to" +
" null, instead. Delegates uses reflection internally, have a non-trivial initialization" +
" cost, and can cause breakages on KitKat devices. See #3939 for more context."
private val screenNameNotPresentErrorMessage =
"Please add a Screen Name for this activity. To do this, add a value in the ScreenName enum " +
"of screens.proto and add that name to your activity using " +
"Intent.decorateWithScreenName(value) on the activity creation intent."
private val screenNameTestNotPresentErrorMessage = "You've not added a test for verifying the " +
"presence of a screen name for this activity. To do this, add a test named " +
"testActivity_createIntent_verifyScreenNameInIntent and verify that an appropriate screen " +
"name has been added to the activity's intent."
private val doNotUseProtoLibrary = "Don't use proto_library. Use oppia_proto_library instead."
private val parameterizedTestRunnerRequiresException =
"To use OppiaParameterizedTestRunner, please add an exemption to" +
" file_content_validation_checks.textproto and add an explanation for your use case in your" +
" PR description. Note that parameterized tests should only be used in special" +
" circumstances where a single behavior can be tested across multiple inputs, or for" +
" especially large test suites that can be trivially reduced."
private val doNotUseClipboardManager =
"Don't use Android's ClipboardManager directly. Instead, use ClipboardController."
private val doesNotHaveColorSuffixOrSnakeCasing =
"All color declarations in component_color.xml and color_palette.xml should end with _color" +
" suffix following snake_case naming convention."
private val hasColorKeywordOrNoSnakeCasing =
"All color declarations in color_defs.xml should be named using snake_case convention and" +
" not contain color keyword."
private val hasHexColorValue =
"Hex color declarations should only be in color_defs.xml and not in component_colors.xml" +
" or color_palette.xml"
private val doesNotHaveRawColorDeclaration =
"color_defs.xml should only have raw hex color declarations."
private val doesNotStartWithComponentColor =
"All colors in component_colors.xml must start with 'component_color_'."
private val doesNotStartWithColorPalette =
"All colors in color_palette.xml must start with 'color_palette_'."
private val doesNotStartWithColorDefs =
"All colors in color_defs.xml must start with 'color_def_'."
private val doesNotReferenceColorFromColorPalette =
"Only colors from color_palette.xml may be used in component_colors.xml."
private val doesNotReferenceColorFromColorDefs =
"Only colors from color_defs.xml may be used in color_palette.xml."
private val doesNotReferenceColorFromComponentColorInLayouts =
"Only colors from component_colors.xml may be used in layouts."
private val doesNotReferenceColorFromComponentColorInDrawables =
"Only colors from component_colors.xml may be used in drawables except vector assets."
private val doesNotReferenceColorFromComponentColorInKotlinFiles =
"Only colors from component_colors.xml may be used in Kotlin Files (Activities, Fragments, " +
"Views and Presenters)."
private val doesNotUseWorkManagerGetInstance =
"Use AnalyticsStartupListener to retrieve an instance of WorkManager rather than fetching one" +
" using getInstance (as the latter may create a WorkManager if one isn't already present, " +
"and the application may intend to disable it)."
private val doesNotUsePostOrPostDelayed =
"Prefer avoiding post() and postDelayed() methods as they can can lead to subtle and " +
"difficult-to-debug crashes. Prefer using LifecycleSafeTimerFactory for most cases when " +
"an operation needs to run at a future time. For cases when state needs to be synchronized " +
"with a view, use doOnPreDraw or doOnLayout instead. For more context on the underlying " +
"issue, see: https://betterprogramming.pub/stop-using-post-postdelayed-in-your" +
"-android-views-9d1c8eeaadf2."
private val badKdocShouldFitOnOneLine =
"Badly formatted KDoc. KDocs should either fit entirely on one line, e.g. \"/** My KDoc. */\"" +
" or on multiple lines with the \"/**\" by itself. See other KDocs in the codebase for" +
" references."
private val badSingleLineKdocShouldHaveSpacesAfterOpening =
"Badly formatted KDoc. Single-line KDocs should have one space after the \"/**\" and no other" +
" characters."
private val badSingleLineKdocShouldHaveExactlyOneSpaceAfterOpening =
"Badly formatted KDoc. Single-line KDocs should have exactly one space after the \"/**\"."
private val badSingleLineKdocShouldHaveSpacesBeforeEnding =
"Badly formatted KDoc. Single-line KDocs should always end with a single space before the" +
" final \"*/\"."
private val badSingleLineKdocShouldHaveExactlyOneSpaceBeforeEnding =
"Badly formatted KDoc. Single-line KDocs should always end with exactly one space before the" +
" final \"*/\"."
private val badKdocOrBlockCommentShouldEndWithCorrectEnding =
"Badly formatted KDoc or block comment. KDocs and block comments should only end with \"*/\"."
private val badKdocParamsAndPropertiesShouldHaveNameFollowing =
"Badly formatted KDoc param or property at-clause: the name of the parameter or property" +
" should immediately follow the at-clause without any additional linking with brackets."
private val badSingleLineKdocShouldEndWithPunctuation =
"Badly formatted KDoc. Single-line KDocs should end with punctuation."
private val activityTestRuleShouldNotBeUsed =
"ActivityTestRule is deprecated since it operates test activities in sometimes unsafe" +
" situations. Use ActivityScenario, instead."
private val activityScenarioRuleShouldNotBeUsed =
"ActivityScenarioRule can result in order dependence when static state leaks across tests" +
" (such as static module variables), and can make staging much more difficult for platform" +
" parameters. Use ActivityScenario directly, instead."
private val referenceComputeIfAbsent =
"computeIfAbsent won't desugar and requires Java 8 support (SDK 24+). Suggest using an atomic" +
" Kotlin-specific solution, instead."
private val cdataShouldNotBeUsed =
"CDATA isn't handled by Translatewiki correctly. Use escaped HTML, instead."
private val wikiReferenceNote =
"Refer to https://github.com/oppia/oppia-android/wiki/Static-Analysis-Checks" +
"#regexpatternvalidation-check for more details on how to fix this."
@Rule
@JvmField
var tempFolder = TemporaryFolder()
@Before
fun setUp() {
tempFolder.newFolder("testfiles")
System.setOut(PrintStream(outContent))
}
@After
fun restoreStreams() {
System.setOut(originalOut)
}
@Test
fun testFileNamePattern_activityInAppModule_fileNamePatternIsCorrect() {
val requiredContent = "decorateWithScreenName(TEST_ACTIVITY)"
tempFolder.newFolder("testfiles", "app", "src", "main")
val tempFile = tempFolder.newFile("testfiles/app/src/main/TestActivity.kt")
tempFile.writeText(requiredContent)
runScript()
assertThat(outContent.toString().trim()).isEqualTo(REGEX_CHECK_PASSED_OUTPUT_INDICATOR)
}
@Test
fun testFileNamePattern_activityInTestingModule_fileNamePatternIsCorrect() {
tempFolder.newFolder("testfiles", "testing", "src", "main")
tempFolder.newFile("testfiles/testing/src/main/TestActivity.kt")
runScript()
assertThat(outContent.toString().trim()).isEqualTo(REGEX_CHECK_PASSED_OUTPUT_INDICATOR)
}
@Test
fun testFileNamePattern_activityInDataModule_fileNamePatternIsNotCorrect() {
val requiredContent = "decorateWithScreenName(TEST_ACTIVITY)"
tempFolder.newFolder("testfiles", "data", "src", "main")
val tempFile = tempFolder.newFile("testfiles/data/src/main/TestActivity.kt")
tempFile.writeText(requiredContent)
val exception = assertThrows<Exception>() { runScript() }
assertThat(exception).hasMessageThat().contains(REGEX_CHECK_FAILED_OUTPUT_INDICATOR)
assertThat(outContent.toString().trim()).isEqualTo(
"""
File name/path violation: $activitiesPlacementErrorMessage
- data/src/main/TestActivity.kt
$wikiReferenceNote
""".trimIndent()
)
}
@Test
fun testFileNamePattern_appResources_stringsFile_fileNamePatternIsCorrect() {
tempFolder.newFolder("testfiles", "app", "src", "main", "res", "values")
tempFolder.newFile("testfiles/app/src/main/res/values/strings.xml")
runScript()
assertThat(outContent.toString().trim()).isEqualTo(REGEX_CHECK_PASSED_OUTPUT_INDICATOR)
}
@Test
fun testFileNamePattern_appResources_subValuesDir_stringsFile_fileNamePatternIsNotCorrect() {
tempFolder.newFolder("testfiles", "app", "src", "main", "res", "values", "subdir")
tempFolder.newFile("testfiles/app/src/main/res/values/subdir/strings.xml")
val exception = assertThrows<Exception>() { runScript() }
assertThat(exception).hasMessageThat().contains(REGEX_CHECK_FAILED_OUTPUT_INDICATOR)
assertThat(outContent.toString().trim()).isEqualTo(
"""
File name/path violation: $nestedResourceSubdirectoryErrorMessage
- app/src/main/res/values/subdir/strings.xml
$wikiReferenceNote
""".trimIndent()
)
}
@Test
fun testFileNamePattern_domainResources_subValuesDir_stringsFile_fileNamePatternIsNotCorrect() {
tempFolder.newFolder("testfiles", "domain", "src", "main", "res", "drawable", "subdir")
tempFolder.newFile("testfiles/domain/src/main/res/drawable/subdir/example.png")
val exception = assertThrows<Exception>() { runScript() }
assertThat(exception).hasMessageThat().contains(REGEX_CHECK_FAILED_OUTPUT_INDICATOR)
assertThat(outContent.toString().trim()).isEqualTo(
"""
File name/path violation: $nestedResourceSubdirectoryErrorMessage
- domain/src/main/res/drawable/subdir/example.png
$wikiReferenceNote
""".trimIndent()
)
}
@Test
fun testFileContent_emptyFile_fileContentIsCorrect() {
tempFolder.newFile("testfiles/TestFile.kt")
runScript()
assertThat(outContent.toString().trim()).isEqualTo(REGEX_CHECK_PASSED_OUTPUT_INDICATOR)
}
@Test
fun testFileContent_supportLibraryImport_fileContentIsNotCorrect() {
val prohibitedContent = "import android.support.v7.app"
val fileContainsSupportLibraryImport = tempFolder.newFile("testfiles/TestFile.kt")
fileContainsSupportLibraryImport.writeText(prohibitedContent)
val exception = assertThrows<Exception>() { runScript() }
assertThat(exception).hasMessageThat().contains(REGEX_CHECK_FAILED_OUTPUT_INDICATOR)
assertThat(outContent.toString().trim())
.isEqualTo(
"""
TestFile.kt:1: $supportLibraryUsageErrorMessage
$wikiReferenceNote
""".trimIndent()
)
}
@Test
fun testFileContent_coroutineWorker_fileContentIsNotCorrect() {
val prohibitedContent = ") : CoroutineWorker(context, params) {"
val fileContainsSupportLibraryImport = tempFolder.newFile("testfiles/TestFile.kt")
fileContainsSupportLibraryImport.writeText(prohibitedContent)
val exception = assertThrows<Exception>() { runScript() }
assertThat(exception).hasMessageThat().contains(REGEX_CHECK_FAILED_OUTPUT_INDICATOR)
assertThat(outContent.toString().trim())
.isEqualTo(
"""
TestFile.kt:1: $coroutineWorkerUsageErrorMessage
$wikiReferenceNote
""".trimIndent()
)
}
@Test
fun testFileContent_announceForAccessibilityUsageErrorMessage_fileContentIsNotCorrect() {
val prohibitedContent = "announceForAccessibility("
val fileContainsSupportLibraryImport = tempFolder.newFile("testfiles/TestFile.kt")
fileContainsSupportLibraryImport.writeText(prohibitedContent)
val exception = assertThrows<Exception>() { runScript() }
assertThat(exception).hasMessageThat().contains(REGEX_CHECK_FAILED_OUTPUT_INDICATOR)
assertThat(outContent.toString().trim())
.isEqualTo(
"""
TestFile.kt:1: $announceForAccessibilityUsageErrorMessage
$wikiReferenceNote
""".trimIndent()
)
}
@Test
fun testFileContent_announceForAccessibilityForViewUsageErrorMessage_fileContentIsNotCorrect() {
val prohibitedContent = "announceForAccessibilityForView("
val fileContainsSupportLibraryImport = tempFolder.newFile("testfiles/TestFile.kt")
fileContainsSupportLibraryImport.writeText(prohibitedContent)
val exception = assertThrows<Exception>() { runScript() }
assertThat(exception).hasMessageThat().contains(REGEX_CHECK_FAILED_OUTPUT_INDICATOR)
assertThat(outContent.toString().trim())
.isEqualTo(
"""
TestFile.kt:1: $announceForAccessibilityForViewUsageErrorMessage
$wikiReferenceNote
""".trimIndent()
)
}
@Test
fun testFileContent_settableFuture_fileContentIsNotCorrect() {
val prohibitedContent = "SettableFuture.create<Result>()"
val fileContainsSupportLibraryImport = tempFolder.newFile("testfiles/TestFile.kt")
fileContainsSupportLibraryImport.writeText(prohibitedContent)
val exception = assertThrows<Exception>() { runScript() }
assertThat(exception).hasMessageThat().contains(REGEX_CHECK_FAILED_OUTPUT_INDICATOR)
assertThat(outContent.toString().trim())
.isEqualTo(
"""
TestFile.kt:1: $settableFutureUsageErrorMessage
$wikiReferenceNote
""".trimIndent()
)
}
@Test
fun testFileContent_androidLayoutIncludeTag_fileContentIsNotCorrect() {
val prohibitedContent = "<include"
val fileContainsSupportLibraryImport = tempFolder.newFile("testfiles/test_layout.xml")
fileContainsSupportLibraryImport.writeText(prohibitedContent)
val exception = assertThrows<Exception>() { runScript() }
assertThat(exception).hasMessageThat().contains(REGEX_CHECK_FAILED_OUTPUT_INDICATOR)
assertThat(outContent.toString().trim())
.isEqualTo(
"""
test_layout.xml:1: $androidLayoutIncludeTagErrorMessage
$wikiReferenceNote
""".trimIndent()
)
}
@Test
fun testFileContent_androidGravityLeft_fileContentIsNotCorrect() {
val prohibitedContent = "android:gravity=\"left\""
val fileContainsSupportLibraryImport = tempFolder.newFile("testfiles/test_layout.xml")
fileContainsSupportLibraryImport.writeText(prohibitedContent)
val exception = assertThrows<Exception>() { runScript() }
assertThat(exception).hasMessageThat().contains(REGEX_CHECK_FAILED_OUTPUT_INDICATOR)
assertThat(outContent.toString().trim())
.isEqualTo(
"""
test_layout.xml:1: $androidGravityLeftErrorMessage
$wikiReferenceNote
""".trimIndent()
)
}
@Test
fun testFileContent_androidGravityRight_fileContentIsNotCorrect() {
val prohibitedContent = "android:gravity=\"right\""
val fileContainsSupportLibraryImport = tempFolder.newFile("testfiles/test_layout.xml")
fileContainsSupportLibraryImport.writeText(prohibitedContent)
val exception = assertThrows<Exception>() { runScript() }
assertThat(exception).hasMessageThat().contains(REGEX_CHECK_FAILED_OUTPUT_INDICATOR)
assertThat(outContent.toString().trim())
.isEqualTo(
"""
test_layout.xml:1: $androidGravityRightErrorMessage
$wikiReferenceNote
""".trimIndent()
)
}
@Test
fun testFileContent_androidLayoutGravityLeft_fileContentIsNotCorrect() {
val prohibitedContent = "android:layout_gravity=\"left\""
val fileContainsSupportLibraryImport = tempFolder.newFile("testfiles/test_layout.xml")
fileContainsSupportLibraryImport.writeText(prohibitedContent)
val exception = assertThrows<Exception>() { runScript() }
assertThat(exception).hasMessageThat().contains(REGEX_CHECK_FAILED_OUTPUT_INDICATOR)
assertThat(outContent.toString().trim())
.isEqualTo(
"""
test_layout.xml:1: $androidLayoutGravityLeftErrorMessage
$wikiReferenceNote
""".trimIndent()
)
}
@Test
fun testFileContent_androidLayoutGravityRight_fileContentIsNotCorrect() {
val prohibitedContent = "android:layout_gravity=\"right\""
val fileContainsSupportLibraryImport = tempFolder.newFile("testfiles/test_layout.xml")
fileContainsSupportLibraryImport.writeText(prohibitedContent)
val exception = assertThrows<Exception>() { runScript() }
assertThat(exception).hasMessageThat().contains(REGEX_CHECK_FAILED_OUTPUT_INDICATOR)
assertThat(outContent.toString().trim())
.isEqualTo(
"""
test_layout.xml:1: $androidLayoutGravityRightErrorMessage
$wikiReferenceNote
""".trimIndent()
)
}
@Test
fun testFileContent_androidPaddingLeft_fileContentIsNotCorrect() {
val prohibitedContent = "android:paddingLeft=\"16dp\""
val fileContainsSupportLibraryImport = tempFolder.newFile("testfiles/test_layout.xml")
fileContainsSupportLibraryImport.writeText(prohibitedContent)
val exception = assertThrows<Exception>() { runScript() }
assertThat(exception).hasMessageThat().contains(REGEX_CHECK_FAILED_OUTPUT_INDICATOR)
assertThat(outContent.toString().trim())
.isEqualTo(
"""
test_layout.xml:1: $androidGenericStartEndRtlErrorMessage
$wikiReferenceNote
""".trimIndent()
)
}
@Test
fun testFileContent_androidPaddingRight_fileContentIsNotCorrect() {
val prohibitedContent = "android:paddingRight=\"16dp\""
val fileContainsSupportLibraryImport = tempFolder.newFile("testfiles/test_layout.xml")
fileContainsSupportLibraryImport.writeText(prohibitedContent)
val exception = assertThrows<Exception>() { runScript() }
assertThat(exception).hasMessageThat().contains(REGEX_CHECK_FAILED_OUTPUT_INDICATOR)
assertThat(outContent.toString().trim())
.isEqualTo(
"""
test_layout.xml:1: $androidGenericStartEndRtlErrorMessage
$wikiReferenceNote
""".trimIndent()
)
}
@Test
fun testFileContent_androidDrawableLeft_fileContentIsNotCorrect() {
val prohibitedContent = "android:drawableLeft=\"@android:color/transparent\""
val fileContainsSupportLibraryImport = tempFolder.newFile("testfiles/test_layout.xml")
fileContainsSupportLibraryImport.writeText(prohibitedContent)
val exception = assertThrows<Exception>() { runScript() }
assertThat(exception).hasMessageThat().contains(REGEX_CHECK_FAILED_OUTPUT_INDICATOR)
assertThat(outContent.toString().trim())
.isEqualTo(
"""
test_layout.xml:1: $androidGenericStartEndRtlErrorMessage
$wikiReferenceNote
""".trimIndent()
)
}
@Test
fun testFileContent_androidDrawableRight_fileContentIsNotCorrect() {
val prohibitedContent = "android:drawableRight=\"@android:color/transparent\""
val fileContainsSupportLibraryImport = tempFolder.newFile("testfiles/test_layout.xml")
fileContainsSupportLibraryImport.writeText(prohibitedContent)
val exception = assertThrows<Exception>() { runScript() }
assertThat(exception).hasMessageThat().contains(REGEX_CHECK_FAILED_OUTPUT_INDICATOR)
assertThat(outContent.toString().trim())
.isEqualTo(
"""
test_layout.xml:1: $androidGenericStartEndRtlErrorMessage
$wikiReferenceNote
""".trimIndent()
)
}
@Test
fun testFileContent_androidLayoutAlignLeft_fileContentIsNotCorrect() {
val prohibitedContent = "android:layout_alignLeft=\"@+id/another_view\""
val fileContainsSupportLibraryImport = tempFolder.newFile("testfiles/test_layout.xml")
fileContainsSupportLibraryImport.writeText(prohibitedContent)
val exception = assertThrows<Exception>() { runScript() }
assertThat(exception).hasMessageThat().contains(REGEX_CHECK_FAILED_OUTPUT_INDICATOR)
assertThat(outContent.toString().trim())
.isEqualTo(
"""
test_layout.xml:1: $androidGenericStartEndRtlErrorMessage
$wikiReferenceNote
""".trimIndent()
)
}
@Test
fun testFileContent_androidLayoutAlignRight_fileContentIsNotCorrect() {
val prohibitedContent = "android:layout_alignRight=\"@+id/another_view\""
val fileContainsSupportLibraryImport = tempFolder.newFile("testfiles/test_layout.xml")
fileContainsSupportLibraryImport.writeText(prohibitedContent)
val exception = assertThrows<Exception>() { runScript() }
assertThat(exception).hasMessageThat().contains(REGEX_CHECK_FAILED_OUTPUT_INDICATOR)
assertThat(outContent.toString().trim())
.isEqualTo(
"""
test_layout.xml:1: $androidGenericStartEndRtlErrorMessage
$wikiReferenceNote
""".trimIndent()
)
}
@Test
fun testFileContent_androidLayoutMarginLeft_fileContentIsNotCorrect() {
val prohibitedContent = "android:layout_marginLeft=\"16dp\""
val fileContainsSupportLibraryImport = tempFolder.newFile("testfiles/test_layout.xml")
fileContainsSupportLibraryImport.writeText(prohibitedContent)
val exception = assertThrows<Exception>() { runScript() }
assertThat(exception).hasMessageThat().contains(REGEX_CHECK_FAILED_OUTPUT_INDICATOR)
assertThat(outContent.toString().trim())
.isEqualTo(
"""
test_layout.xml:1: $androidGenericStartEndRtlErrorMessage
$wikiReferenceNote
""".trimIndent()
)
}
@Test
fun testFileContent_androidLayoutMarginRight_fileContentIsNotCorrect() {
val prohibitedContent = "android:layout_marginRight=\"16dp\""
val fileContainsSupportLibraryImport = tempFolder.newFile("testfiles/test_layout.xml")
fileContainsSupportLibraryImport.writeText(prohibitedContent)
val exception = assertThrows<Exception>() { runScript() }
assertThat(exception).hasMessageThat().contains(REGEX_CHECK_FAILED_OUTPUT_INDICATOR)
assertThat(outContent.toString().trim())
.isEqualTo(
"""
test_layout.xml:1: $androidGenericStartEndRtlErrorMessage
$wikiReferenceNote
""".trimIndent()
)
}
@Test
fun testFileContent_androidLayoutAlignParentLeft_fileContentIsNotCorrect() {
val prohibitedContent = "android:layout_alignParentLeft=\"true\""
val fileContainsSupportLibraryImport = tempFolder.newFile("testfiles/test_layout.xml")
fileContainsSupportLibraryImport.writeText(prohibitedContent)
val exception = assertThrows<Exception>() { runScript() }
assertThat(exception).hasMessageThat().contains(REGEX_CHECK_FAILED_OUTPUT_INDICATOR)
assertThat(outContent.toString().trim())
.isEqualTo(
"""
test_layout.xml:1: $androidGenericStartEndRtlErrorMessage
$wikiReferenceNote
""".trimIndent()
)
}
@Test
fun testFileContent_androidLayoutAlignParentRight_fileContentIsNotCorrect() {
val prohibitedContent = "android:layout_alignParentRight=\"true\""
val fileContainsSupportLibraryImport = tempFolder.newFile("testfiles/test_layout.xml")
fileContainsSupportLibraryImport.writeText(prohibitedContent)
val exception = assertThrows<Exception>() { runScript() }
assertThat(exception).hasMessageThat().contains(REGEX_CHECK_FAILED_OUTPUT_INDICATOR)
assertThat(outContent.toString().trim())
.isEqualTo(
"""
test_layout.xml:1: $androidGenericStartEndRtlErrorMessage
$wikiReferenceNote
""".trimIndent()
)
}
@Test
fun testFileContent_androidLayoutToLeftOf_fileContentIsNotCorrect() {
val prohibitedContent = "android:layout_toLeftOf=\"@+id/another_view\""
val fileContainsSupportLibraryImport = tempFolder.newFile("testfiles/test_layout.xml")
fileContainsSupportLibraryImport.writeText(prohibitedContent)
val exception = assertThrows<Exception>() { runScript() }
assertThat(exception).hasMessageThat().contains(REGEX_CHECK_FAILED_OUTPUT_INDICATOR)
assertThat(outContent.toString().trim())
.isEqualTo(
"""
test_layout.xml:1: $androidGenericStartEndRtlErrorMessage
$wikiReferenceNote
""".trimIndent()
)
}
@Test
fun testFileContent_androidLayoutToRightOf_fileContentIsNotCorrect() {
val prohibitedContent = "android:layout_toRightOf=\"@+id/another_view\""
val fileContainsSupportLibraryImport = tempFolder.newFile("testfiles/test_layout.xml")
fileContainsSupportLibraryImport.writeText(prohibitedContent)
val exception = assertThrows<Exception>() { runScript() }
assertThat(exception).hasMessageThat().contains(REGEX_CHECK_FAILED_OUTPUT_INDICATOR)
assertThat(outContent.toString().trim())
.isEqualTo(
"""
test_layout.xml:1: $androidGenericStartEndRtlErrorMessage
$wikiReferenceNote
""".trimIndent()
)
}
@Test
fun testFileContent_androidLayoutConstraintLeftToLeftOf_fileContentIsNotCorrect() {
val prohibitedContent = "android:layout_constraintLeft_toLeftOf=\"@+id/another_view\""
val fileContainsSupportLibraryImport = tempFolder.newFile("testfiles/test_layout.xml")
fileContainsSupportLibraryImport.writeText(prohibitedContent)
val exception = assertThrows<Exception>() { runScript() }
assertThat(exception).hasMessageThat().contains(REGEX_CHECK_FAILED_OUTPUT_INDICATOR)
assertThat(outContent.toString().trim())
.isEqualTo(
"""
test_layout.xml:1: $androidGenericStartEndRtlErrorMessage
$wikiReferenceNote
""".trimIndent()
)
}
@Test
fun testFileContent_androidLayoutConstraintLeftToRightOf_fileContentIsNotCorrect() {
val prohibitedContent = "android:layout_constraintLeft_toRightOf=\"@+id/another_view\""
val fileContainsSupportLibraryImport = tempFolder.newFile("testfiles/test_layout.xml")
fileContainsSupportLibraryImport.writeText(prohibitedContent)
val exception = assertThrows<Exception>() { runScript() }
assertThat(exception).hasMessageThat().contains(REGEX_CHECK_FAILED_OUTPUT_INDICATOR)
assertThat(outContent.toString().trim())
.isEqualTo(
"""
test_layout.xml:1: $androidGenericStartEndRtlErrorMessage
$wikiReferenceNote
""".trimIndent()
)
}
@Test
fun testFileContent_androidLayoutConstraintRightToLeftOf_fileContentIsNotCorrect() {
val prohibitedContent = "android:layout_constraintRight_toLeftOf=\"@+id/another_view\""
val fileContainsSupportLibraryImport = tempFolder.newFile("testfiles/test_layout.xml")
fileContainsSupportLibraryImport.writeText(prohibitedContent)
val exception = assertThrows<Exception>() { runScript() }
assertThat(exception).hasMessageThat().contains(REGEX_CHECK_FAILED_OUTPUT_INDICATOR)
assertThat(outContent.toString().trim())
.isEqualTo(
"""
test_layout.xml:1: $androidGenericStartEndRtlErrorMessage
$wikiReferenceNote
""".trimIndent()
)
}
@Test
fun testFileContent_androidLayoutConstraintRightToRightOf_fileContentIsNotCorrect() {
val prohibitedContent = "android:layout_constraintRight_toRightOf=\"@+id/another_view\""
val fileContainsSupportLibraryImport = tempFolder.newFile("testfiles/test_layout.xml")
fileContainsSupportLibraryImport.writeText(prohibitedContent)
val exception = assertThrows<Exception>() { runScript() }
assertThat(exception).hasMessageThat().contains(REGEX_CHECK_FAILED_OUTPUT_INDICATOR)
assertThat(outContent.toString().trim())
.isEqualTo(
"""
test_layout.xml:1: $androidGenericStartEndRtlErrorMessage
$wikiReferenceNote
""".trimIndent()
)
}
@Test
fun testFileContent_androidLayoutGoneMarginLeft_fileContentIsNotCorrect() {
val prohibitedContent = "android:layout_goneMarginLeft=\"16dp\""
val fileContainsSupportLibraryImport = tempFolder.newFile("testfiles/test_layout.xml")
fileContainsSupportLibraryImport.writeText(prohibitedContent)
val exception = assertThrows<Exception>() { runScript() }
assertThat(exception).hasMessageThat().contains(REGEX_CHECK_FAILED_OUTPUT_INDICATOR)
assertThat(outContent.toString().trim())
.isEqualTo(
"""
test_layout.xml:1: $androidGenericStartEndRtlErrorMessage
$wikiReferenceNote
""".trimIndent()
)
}
@Test
fun testFileContent_androidLayoutGoneMarginRight_fileContentIsNotCorrect() {
val prohibitedContent = "android:layout_goneMarginRight=\"16dp\""
val fileContainsSupportLibraryImport = tempFolder.newFile("testfiles/test_layout.xml")
fileContainsSupportLibraryImport.writeText(prohibitedContent)
val exception = assertThrows<Exception>() { runScript() }
assertThat(exception).hasMessageThat().contains(REGEX_CHECK_FAILED_OUTPUT_INDICATOR)
assertThat(outContent.toString().trim())
.isEqualTo(
"""
test_layout.xml:1: $androidGenericStartEndRtlErrorMessage
$wikiReferenceNote
""".trimIndent()
)
}
@Test
fun testFileContent_appBarrierDirectionLeft_fileContentIsNotCorrect() {
val prohibitedContent = "app:barrierDirection=\"left\""
val fileContainsSupportLibraryImport = tempFolder.newFile("testfiles/test_layout.xml")
fileContainsSupportLibraryImport.writeText(prohibitedContent)
val exception = assertThrows<Exception>() { runScript() }
assertThat(exception).hasMessageThat().contains(REGEX_CHECK_FAILED_OUTPUT_INDICATOR)
assertThat(outContent.toString().trim())
.isEqualTo(
"""
test_layout.xml:1: $androidBarrierDirectionLeftErrorMessage
$wikiReferenceNote
""".trimIndent()
)
}
@Test
fun testFileContent_appBarrierDirectionRight_fileContentIsNotCorrect() {
val prohibitedContent = "app:barrierDirection=\"right\""
val fileContainsSupportLibraryImport = tempFolder.newFile("testfiles/test_layout.xml")
fileContainsSupportLibraryImport.writeText(prohibitedContent)
val exception = assertThrows<Exception>() { runScript() }
assertThat(exception).hasMessageThat().contains(REGEX_CHECK_FAILED_OUTPUT_INDICATOR)
assertThat(outContent.toString().trim())
.isEqualTo(
"""
test_layout.xml:1: $androidBarrierDirectionRightErrorMessage
$wikiReferenceNote
""".trimIndent()
)
}
@Test
fun testFileContent_appDragDirectionLeft_fileContentIsNotCorrect() {
val prohibitedContent = "motion:dragDirection=\"left\""
val fileContainsSupportLibraryImport = tempFolder.newFile("testfiles/test_layout.xml")
fileContainsSupportLibraryImport.writeText(prohibitedContent)
val exception = assertThrows<Exception>() { runScript() }
assertThat(exception).hasMessageThat().contains(REGEX_CHECK_FAILED_OUTPUT_INDICATOR)
assertThat(outContent.toString().trim())
.isEqualTo(
"""
test_layout.xml:1: $androidDragDirectionLeftErrorMessage
$wikiReferenceNote
""".trimIndent()
)
}
@Test
fun testFileContent_appDragDirectionRight_fileContentIsNotCorrect() {
val prohibitedContent = "motion:dragDirection=\"right\""
val fileContainsSupportLibraryImport = tempFolder.newFile("testfiles/test_layout.xml")
fileContainsSupportLibraryImport.writeText(prohibitedContent)
val exception = assertThrows<Exception>() { runScript() }
assertThat(exception).hasMessageThat().contains(REGEX_CHECK_FAILED_OUTPUT_INDICATOR)
assertThat(outContent.toString().trim())
.isEqualTo(
"""
test_layout.xml:1: $androidDragDirectionRightErrorMessage
$wikiReferenceNote
""".trimIndent()
)
}
@Test
fun testFileContent_appTouchAnchorSideLeft_fileContentIsNotCorrect() {
val prohibitedContent = "motion:touchAnchorSide=\"left\""
val fileContainsSupportLibraryImport = tempFolder.newFile("testfiles/test_layout.xml")
fileContainsSupportLibraryImport.writeText(prohibitedContent)
val exception = assertThrows<Exception>() { runScript() }
assertThat(exception).hasMessageThat().contains(REGEX_CHECK_FAILED_OUTPUT_INDICATOR)
assertThat(outContent.toString().trim())
.isEqualTo(
"""
test_layout.xml:1: $androidTouchAnchorSideLeftErrorMessage
$wikiReferenceNote
""".trimIndent()
)
}
@Test
fun testFileContent_appTouchAnchorSideRight_fileContentIsNotCorrect() {
val prohibitedContent = "motion:touchAnchorSide=\"right\""
val fileContainsSupportLibraryImport = tempFolder.newFile("testfiles/test_layout.xml")
fileContainsSupportLibraryImport.writeText(prohibitedContent)
val exception = assertThrows<Exception>() { runScript() }
assertThat(exception).hasMessageThat().contains(REGEX_CHECK_FAILED_OUTPUT_INDICATOR)
assertThat(outContent.toString().trim())
.isEqualTo(
"""
test_layout.xml:1: $androidTouchAnchorSideRightErrorMessage
$wikiReferenceNote
""".trimIndent()
)
}
@Test
fun testFileContent_oppiaInString_inPrimaryStringsFile_fileContentIsNotCorrect() {
val prohibitedContent = "<string name=\"test\">String with Oppia in it</string>"
tempFolder.newFolder("testfiles", "app", "src", "main", "res", "values")
val stringFilePath = "app/src/main/res/values/strings.xml"
tempFolder.newFile("testfiles/$stringFilePath").writeText(prohibitedContent)
val exception = assertThrows<Exception>() { runScript() }
assertThat(exception).hasMessageThat().contains(REGEX_CHECK_FAILED_OUTPUT_INDICATOR)
assertThat(outContent.toString().trim())
.isEqualTo(
"""
$stringFilePath:1: $oppiaCantBeTranslatedErrorMessage
$wikiReferenceNote
""".trimIndent()
)
}
@Test
fun testFileContent_untranslatableString_inPrimaryStringsFile_fileContentIsNotCorrect() {
val prohibitedContent = "<string name=\"test\" translatable=\"false\">Something</string>"
tempFolder.newFolder("testfiles", "app", "src", "main", "res", "values")
val stringFilePath = "app/src/main/res/values/strings.xml"
tempFolder.newFile("testfiles/$stringFilePath").writeText(prohibitedContent)
val exception = assertThrows<Exception>() { runScript() }
assertThat(exception).hasMessageThat().contains(REGEX_CHECK_FAILED_OUTPUT_INDICATOR)
assertThat(outContent.toString().trim())
.isEqualTo(
"""
$stringFilePath:1: $untranslatableStringsGoInSpecificFileErrorMessage
$wikiReferenceNote
""".trimIndent()
)
}
@Test
fun testFileContent_untranslatableString_inUntranslatedStringsFile_fileContentIsCorrect() {
val prohibitedContent = "<string name=\"test\" translatable=\"false\">Something</string>"
tempFolder.newFolder("testfiles", "app", "src", "main", "res", "values")
val stringFilePath = "app/src/main/res/values/untranslated_strings.xml"
tempFolder.newFile("testfiles/$stringFilePath").writeText(prohibitedContent)
runScript()