Java

Форк
0
/
NullPointerTesterTest.java 
1528 строк · 47.7 Кб
1
/*
2
 * Copyright (C) 2005 The Guava Authors
3
 *
4
 * Licensed under the Apache License, Version 2.0 (the "License");
5
 * you may not use this file except in compliance with the License.
6
 * You may obtain a copy of the License at
7
 *
8
 * http://www.apache.org/licenses/LICENSE-2.0
9
 *
10
 * Unless required by applicable law or agreed to in writing, software
11
 * distributed under the License is distributed on an "AS IS" BASIS,
12
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
 * See the License for the specific language governing permissions and
14
 * limitations under the License.
15
 */
16

17
package com.google.common.testing;
18

19
import static com.google.common.base.Preconditions.checkArgument;
20
import static com.google.common.base.Preconditions.checkNotNull;
21
import static com.google.common.truth.Truth.assertThat;
22
import static org.junit.Assert.assertThrows;
23

24
import com.google.common.base.Converter;
25
import com.google.common.base.Function;
26
import com.google.common.base.Supplier;
27
import com.google.common.collect.ImmutableList;
28
import com.google.common.collect.ImmutableMap;
29
import com.google.common.collect.ImmutableMultimap;
30
import com.google.common.collect.ImmutableMultiset;
31
import com.google.common.collect.ImmutableSet;
32
import com.google.common.collect.ImmutableSortedSet;
33
import com.google.common.collect.ImmutableTable;
34
import com.google.common.collect.Maps;
35
import com.google.common.collect.Multimap;
36
import com.google.common.collect.Multiset;
37
import com.google.common.collect.Table;
38
import com.google.common.reflect.TypeToken;
39
import com.google.common.testing.NullPointerTester.Visibility;
40
import com.google.common.testing.anotherpackage.SomeClassThatDoesNotUseNullable;
41
import com.google.errorprone.annotations.CanIgnoreReturnValue;
42
import java.lang.reflect.Constructor;
43
import java.lang.reflect.Method;
44
import java.util.List;
45
import java.util.Locale;
46
import java.util.Map;
47
import java.util.Set;
48
import java.util.SortedSet;
49
import javax.annotation.CheckForNull;
50
import junit.framework.TestCase;
51
import org.checkerframework.checker.nullness.qual.Nullable;
52

53
/**
54
 * Unit test for {@link NullPointerTester}.
55
 *
56
 * @author Kevin Bourrillion
57
 * @author Mick Killianey
58
 */
59
@SuppressWarnings("CheckReturnValue")
60
public class NullPointerTesterTest extends TestCase {
61

62
  /** Non-NPE RuntimeException. */
63
  public static class FooException extends RuntimeException {
64
    private static final long serialVersionUID = 1L;
65
  }
66

67
  /**
68
   * Class for testing all permutations of static/non-static one-argument methods using
69
   * methodParameter().
70
   */
71
  @SuppressWarnings("unused") // used by reflection
72
  public static class OneArg {
73

74
    public static void staticOneArgCorrectlyThrowsNpe(String s) {
75
      checkNotNull(s); // expect NPE here on null
76
    }
77

78
    public static void staticOneArgThrowsOtherThanNpe(String s) {
79
      throw new FooException(); // should catch as failure
80
    }
81

82
    public static void staticOneArgShouldThrowNpeButDoesnt(String s) {
83
      // should catch as failure
84
    }
85

86
    public static void staticOneArgCheckForNullCorrectlyDoesNotThrowNPE(@CheckForNull String s) {
87
      // null?  no problem
88
    }
89

90
    public static void staticOneArgJsr305NullableCorrectlyDoesNotThrowNPE(
91
        @javax.annotation.Nullable String s) {
92
      // null?  no problem
93
    }
94

95
    public static void staticOneArgNullableCorrectlyDoesNotThrowNPE(@Nullable String s) {
96
      // null?  no problem
97
    }
98

99
    public static void staticOneArgCheckForNullCorrectlyThrowsOtherThanNPE(@CheckForNull String s) {
100
      throw new FooException(); // ok, as long as it's not NullPointerException
101
    }
102

103
    public static void staticOneArgNullableCorrectlyThrowsOtherThanNPE(@Nullable String s) {
104
      throw new FooException(); // ok, as long as it's not NullPointerException
105
    }
106

107
    public static void staticOneArgCheckForNullThrowsNPE(@CheckForNull String s) {
108
      checkNotNull(s); // doesn't check if you said you'd accept null, but you don't
109
    }
110

111
    public static void staticOneArgNullableThrowsNPE(@Nullable String s) {
112
      checkNotNull(s); // doesn't check if you said you'd accept null, but you don't
113
    }
114

115
    public void oneArgCorrectlyThrowsNpe(String s) {
116
      checkNotNull(s); // expect NPE here on null
117
    }
118

119
    public void oneArgThrowsOtherThanNpe(String s) {
120
      throw new FooException(); // should catch as failure
121
    }
122

123
    public void oneArgShouldThrowNpeButDoesnt(String s) {
124
      // should catch as failure
125
    }
126

127
    public void oneArgCheckForNullCorrectlyDoesNotThrowNPE(@CheckForNull String s) {
128
      // null?  no problem
129
    }
130

131
    public void oneArgNullableCorrectlyDoesNotThrowNPE(@Nullable String s) {
132
      // null?  no problem
133
    }
134

135
    public void oneArgCheckForNullCorrectlyThrowsOtherThanNPE(@CheckForNull String s) {
136
      throw new FooException(); // ok, as long as it's not NullPointerException
137
    }
138

139
    public void oneArgNullableCorrectlyThrowsOtherThanNPE(@Nullable String s) {
140
      throw new FooException(); // ok, as long as it's not NullPointerException
141
    }
142

143
    public void oneArgCheckForNullThrowsNPE(@CheckForNull String s) {
144
      checkNotNull(s); // doesn't check if you said you'd accept null, but you don't
145
    }
146

147
    public void oneArgNullableThrowsNPE(@Nullable String s) {
148
      checkNotNull(s); // doesn't check if you said you'd accept null, but you don't
149
    }
150
  }
151

152
  private static final String[] STATIC_ONE_ARG_METHODS_SHOULD_PASS = {
153
    "staticOneArgCorrectlyThrowsNpe",
154
    "staticOneArgCheckForNullCorrectlyDoesNotThrowNPE",
155
    "staticOneArgCheckForNullCorrectlyThrowsOtherThanNPE",
156
    "staticOneArgCheckForNullThrowsNPE",
157
    "staticOneArgNullableCorrectlyDoesNotThrowNPE",
158
    "staticOneArgNullableCorrectlyThrowsOtherThanNPE",
159
    "staticOneArgNullableThrowsNPE",
160
  };
161
  private static final String[] STATIC_ONE_ARG_METHODS_SHOULD_FAIL = {
162
    "staticOneArgThrowsOtherThanNpe", "staticOneArgShouldThrowNpeButDoesnt",
163
  };
164
  private static final String[] NONSTATIC_ONE_ARG_METHODS_SHOULD_PASS = {
165
    "oneArgCorrectlyThrowsNpe",
166
    "oneArgCheckForNullCorrectlyDoesNotThrowNPE",
167
    "oneArgCheckForNullCorrectlyThrowsOtherThanNPE",
168
    "oneArgCheckForNullThrowsNPE",
169
    "oneArgNullableCorrectlyDoesNotThrowNPE",
170
    "oneArgNullableCorrectlyThrowsOtherThanNPE",
171
    "oneArgNullableThrowsNPE",
172
  };
173
  private static final String[] NONSTATIC_ONE_ARG_METHODS_SHOULD_FAIL = {
174
    "oneArgThrowsOtherThanNpe", "oneArgShouldThrowNpeButDoesnt",
175
  };
176

177
  private static class ThrowsIae {
178
    public static void christenPoodle(String name) {
179
      checkArgument(name != null);
180
    }
181
  }
182

183
  private static class ThrowsNpe {
184
    public static void christenPoodle(String name) {
185
      checkNotNull(name);
186
    }
187
  }
188

189
  private static class ThrowsUoe {
190
    public static void christenPoodle(String unused) {
191
      throw new UnsupportedOperationException();
192
    }
193
  }
194

195
  private static class ThrowsSomethingElse {
196
    public static void christenPoodle(String unused) {
197
      throw new RuntimeException();
198
    }
199
  }
200

201
  private interface InterfaceStaticMethodFailsToCheckNull {
202
    static String create(String unused) {
203
      return "I don't check";
204
    }
205
  }
206

207
  private interface InterfaceStaticMethodChecksNull {
208
    static String create(String s) {
209
      return checkNotNull(s);
210
    }
211
  }
212

213
  private interface InterfaceDefaultMethodFailsToCheckNull {
214
    static InterfaceDefaultMethodFailsToCheckNull create() {
215
      return new InterfaceDefaultMethodFailsToCheckNull() {};
216
    }
217

218
    default void doNotCheckNull(String unused) {}
219
  }
220

221
  private interface InterfaceDefaultMethodChecksNull {
222
    static InterfaceDefaultMethodChecksNull create() {
223
      return new InterfaceDefaultMethodChecksNull() {};
224
    }
225

226
    default void checksNull(String s) {
227
      checkNotNull(s);
228
    }
229
  }
230

231
  public void testInterfaceStaticMethod() {
232
    NullPointerTester tester = new NullPointerTester();
233
    tester.testAllPublicStaticMethods(InterfaceStaticMethodChecksNull.class);
234
    try {
235
      tester.testAllPublicStaticMethods(InterfaceStaticMethodFailsToCheckNull.class);
236
    } catch (AssertionError expected) {
237
      return;
238
    }
239
    fail();
240
  }
241

242
  public void testInterfaceDefaultMethod() {
243
    NullPointerTester tester = new NullPointerTester();
244
    tester.testAllPublicInstanceMethods(InterfaceDefaultMethodChecksNull.create());
245
    try {
246
      tester.testAllPublicInstanceMethods(InterfaceDefaultMethodFailsToCheckNull.create());
247
    } catch (AssertionError expected) {
248
      return;
249
    }
250
    fail();
251
  }
252

253
  public void testDontAcceptIae() {
254
    NullPointerTester tester = new NullPointerTester();
255
    tester.testAllPublicStaticMethods(ThrowsNpe.class);
256
    tester.testAllPublicStaticMethods(ThrowsUoe.class);
257
    try {
258
      tester.testAllPublicStaticMethods(ThrowsIae.class);
259
    } catch (AssertionError expected) {
260
      return;
261
    }
262
    fail();
263
  }
264

265
  public void testStaticOneArgMethodsThatShouldPass() throws Exception {
266
    for (String methodName : STATIC_ONE_ARG_METHODS_SHOULD_PASS) {
267
      Method method = OneArg.class.getMethod(methodName, String.class);
268
      try {
269
        new NullPointerTester().testMethodParameter(new OneArg(), method, 0);
270
      } catch (AssertionError unexpected) {
271
        fail("Should not have flagged method " + methodName);
272
      }
273
    }
274
  }
275

276
  public void testStaticOneArgMethodsThatShouldFail() throws Exception {
277
    for (String methodName : STATIC_ONE_ARG_METHODS_SHOULD_FAIL) {
278
      Method method = OneArg.class.getMethod(methodName, String.class);
279
      boolean foundProblem = false;
280
      try {
281
        new NullPointerTester().testMethodParameter(new OneArg(), method, 0);
282
      } catch (AssertionError expected) {
283
        foundProblem = true;
284
      }
285
      assertTrue("Should report error in method " + methodName, foundProblem);
286
    }
287
  }
288

289
  public void testNonStaticOneArgMethodsThatShouldPass() throws Exception {
290
    OneArg foo = new OneArg();
291
    for (String methodName : NONSTATIC_ONE_ARG_METHODS_SHOULD_PASS) {
292
      Method method = OneArg.class.getMethod(methodName, String.class);
293
      try {
294
        new NullPointerTester().testMethodParameter(foo, method, 0);
295
      } catch (AssertionError unexpected) {
296
        fail("Should not have flagged method " + methodName);
297
      }
298
    }
299
  }
300

301
  public void testNonStaticOneArgMethodsThatShouldFail() throws Exception {
302
    OneArg foo = new OneArg();
303
    for (String methodName : NONSTATIC_ONE_ARG_METHODS_SHOULD_FAIL) {
304
      Method method = OneArg.class.getMethod(methodName, String.class);
305
      boolean foundProblem = false;
306
      try {
307
        new NullPointerTester().testMethodParameter(foo, method, 0);
308
      } catch (AssertionError expected) {
309
        foundProblem = true;
310
      }
311
      assertTrue("Should report error in method " + methodName, foundProblem);
312
    }
313
  }
314

315
  public void testMessageOtherException() throws Exception {
316
    Method method = OneArg.class.getMethod("staticOneArgThrowsOtherThanNpe", String.class);
317
    boolean foundProblem = false;
318
    try {
319
      new NullPointerTester().testMethodParameter(new OneArg(), method, 0);
320
    } catch (AssertionError expected) {
321
      assertThat(expected.getMessage()).contains("index 0");
322
      assertThat(expected.getMessage()).contains("[null]");
323
      foundProblem = true;
324
    }
325
    assertTrue("Should report error when different exception is thrown", foundProblem);
326
  }
327

328
  public void testMessageNoException() throws Exception {
329
    Method method = OneArg.class.getMethod("staticOneArgShouldThrowNpeButDoesnt", String.class);
330
    boolean foundProblem = false;
331
    try {
332
      new NullPointerTester().testMethodParameter(new OneArg(), method, 0);
333
    } catch (AssertionError expected) {
334
      assertThat(expected.getMessage()).contains("index 0");
335
      assertThat(expected.getMessage()).contains("[null]");
336
      foundProblem = true;
337
    }
338
    assertTrue("Should report error when no exception is thrown", foundProblem);
339
  }
340

341
  /**
342
   * Class for testing all permutations of nullable/non-nullable two-argument methods using
343
   * testMethod().
344
   *
345
   * <ul>
346
   *   <li>normalNormal: two params, neither is Nullable
347
   *   <li>nullableNormal: only first param is Nullable
348
   *   <li>normalNullable: only second param is Nullable
349
   *   <li>nullableNullable: both params are Nullable
350
   * </ul>
351
   */
352
  public static class TwoArg {
353
    /** Action to take on a null param. */
354
    public enum Action {
355
      THROW_A_NPE {
356
        @Override
357
        public void act() {
358
          throw new NullPointerException();
359
        }
360
      },
361
      THROW_OTHER {
362
        @Override
363
        public void act() {
364
          throw new FooException();
365
        }
366
      },
367
      JUST_RETURN {
368
        @Override
369
        public void act() {}
370
      };
371

372
      public abstract void act();
373
    }
374

375
    Action actionWhenFirstParamIsNull;
376
    Action actionWhenSecondParamIsNull;
377

378
    public TwoArg(Action actionWhenFirstParamIsNull, Action actionWhenSecondParamIsNull) {
379
      this.actionWhenFirstParamIsNull = actionWhenFirstParamIsNull;
380
      this.actionWhenSecondParamIsNull = actionWhenSecondParamIsNull;
381
    }
382

383
    /** Method that decides how to react to parameters. */
384
    public void reactToNullParameters(@Nullable Object first, @Nullable Object second) {
385
      if (first == null) {
386
        actionWhenFirstParamIsNull.act();
387
      }
388
      if (second == null) {
389
        actionWhenSecondParamIsNull.act();
390
      }
391
    }
392

393
    /** Two-arg method with no Nullable params. */
394
    @SuppressWarnings("GoodTime") // false positive; b/122617528
395
    public void normalNormal(String first, Integer second) {
396
      reactToNullParameters(first, second);
397
    }
398

399
    /** Two-arg method with the second param Nullable. */
400
    @SuppressWarnings("GoodTime") // false positive; b/122617528
401
    public void normalNullable(String first, @Nullable Integer second) {
402
      reactToNullParameters(first, second);
403
    }
404

405
    /** Two-arg method with the first param Nullable. */
406
    @SuppressWarnings("GoodTime") // false positive; b/122617528
407
    public void nullableNormal(@Nullable String first, Integer second) {
408
      reactToNullParameters(first, second);
409
    }
410

411
    /** Two-arg method with the both params Nullable. */
412
    @SuppressWarnings("GoodTime") // false positive; b/122617528
413
    public void nullableNullable(@Nullable String first, @Nullable Integer second) {
414
      reactToNullParameters(first, second);
415
    }
416

417
    /** To provide sanity during debugging. */
418
    @Override
419
    public String toString() {
420
      return rootLocaleFormat(
421
          "Bar(%s, %s)", actionWhenFirstParamIsNull, actionWhenSecondParamIsNull);
422
    }
423
  }
424

425
  public void verifyBarPass(Method method, TwoArg bar) {
426
    try {
427
      new NullPointerTester().testMethod(bar, method);
428
    } catch (AssertionError incorrectError) {
429
      String errorMessage =
430
          rootLocaleFormat("Should not have flagged method %s for %s", method.getName(), bar);
431
      assertNull(errorMessage, incorrectError);
432
    }
433
  }
434

435
  public void verifyBarFail(Method method, TwoArg bar) {
436
    try {
437
      new NullPointerTester().testMethod(bar, method);
438
    } catch (AssertionError expected) {
439
      return; // good...we wanted a failure
440
    }
441
    String errorMessage =
442
        rootLocaleFormat("Should have flagged method %s for %s", method.getName(), bar);
443
    fail(errorMessage);
444
  }
445

446
  public void testTwoArgNormalNormal() throws Exception {
447
    Method method = TwoArg.class.getMethod("normalNormal", String.class, Integer.class);
448
    for (TwoArg.Action first : TwoArg.Action.values()) {
449
      for (TwoArg.Action second : TwoArg.Action.values()) {
450
        TwoArg bar = new TwoArg(first, second);
451
        if (first.equals(TwoArg.Action.THROW_A_NPE) && second.equals(TwoArg.Action.THROW_A_NPE)) {
452
          verifyBarPass(method, bar); // require both params to throw NPE
453
        } else {
454
          verifyBarFail(method, bar);
455
        }
456
      }
457
    }
458
  }
459

460
  public void testTwoArgNormalNullable() throws Exception {
461
    Method method = TwoArg.class.getMethod("normalNullable", String.class, Integer.class);
462
    for (TwoArg.Action first : TwoArg.Action.values()) {
463
      for (TwoArg.Action second : TwoArg.Action.values()) {
464
        TwoArg bar = new TwoArg(first, second);
465
        if (first.equals(TwoArg.Action.THROW_A_NPE)) {
466
          verifyBarPass(method, bar); // only pass if 1st param throws NPE
467
        } else {
468
          verifyBarFail(method, bar);
469
        }
470
      }
471
    }
472
  }
473

474
  public void testTwoArgNullableNormal() throws Exception {
475
    Method method = TwoArg.class.getMethod("nullableNormal", String.class, Integer.class);
476
    for (TwoArg.Action first : TwoArg.Action.values()) {
477
      for (TwoArg.Action second : TwoArg.Action.values()) {
478
        TwoArg bar = new TwoArg(first, second);
479
        if (second.equals(TwoArg.Action.THROW_A_NPE)) {
480
          verifyBarPass(method, bar); // only pass if 2nd param throws NPE
481
        } else {
482
          verifyBarFail(method, bar);
483
        }
484
      }
485
    }
486
  }
487

488
  public void testTwoArgNullableNullable() throws Exception {
489
    Method method = TwoArg.class.getMethod("nullableNullable", String.class, Integer.class);
490
    for (TwoArg.Action first : TwoArg.Action.values()) {
491
      for (TwoArg.Action second : TwoArg.Action.values()) {
492
        TwoArg bar = new TwoArg(first, second);
493
        verifyBarPass(method, bar); // All args nullable:  anything goes!
494
      }
495
    }
496
  }
497

498
  /*
499
   * This next part consists of several sample classes that provide
500
   * demonstrations of conditions that cause NullPointerTester
501
   * to succeed/fail.
502
   */
503

504
  /** Lots of well-behaved methods. */
505
  @SuppressWarnings("unused") // used by reflection
506
  private static class PassObject extends SomeClassThatDoesNotUseNullable {
507
    public static void doThrow(Object arg) {
508
      if (arg == null) {
509
        throw new FooException();
510
      }
511
    }
512

513
    public void noArg() {}
514

515
    public void oneArg(String s) {
516
      checkNotNull(s);
517
    }
518

519
    void packagePrivateOneArg(String s) {
520
      checkNotNull(s);
521
    }
522

523
    protected void protectedOneArg(String s) {
524
      checkNotNull(s);
525
    }
526

527
    public void oneNullableArg(@Nullable String s) {}
528

529
    public void oneNullableArgThrows(@Nullable String s) {
530
      doThrow(s);
531
    }
532

533
    public void twoArg(String s, Integer i) {
534
      checkNotNull(s);
535
      i.intValue();
536
    }
537

538
    public void twoMixedArgs(String s, @Nullable Integer i) {
539
      checkNotNull(s);
540
    }
541

542
    public void twoMixedArgs(@Nullable Integer i, String s) {
543
      checkNotNull(s);
544
    }
545

546
    public void twoMixedArgsThrows(String s, @Nullable Integer i) {
547
      checkNotNull(s);
548
      doThrow(i);
549
    }
550

551
    public void twoMixedArgsThrows(@Nullable Integer i, String s) {
552
      checkNotNull(s);
553
      doThrow(i);
554
    }
555

556
    public void twoNullableArgs(@Nullable String s, @javax.annotation.Nullable Integer i) {}
557

558
    public void twoNullableArgsThrowsFirstArg(@Nullable String s, @Nullable Integer i) {
559
      doThrow(s);
560
    }
561

562
    public void twoNullableArgsThrowsSecondArg(@Nullable String s, @Nullable Integer i) {
563
      doThrow(i);
564
    }
565

566
    public static void staticOneArg(String s) {
567
      checkNotNull(s);
568
    }
569

570
    public static void staticOneNullableArg(@Nullable String s) {}
571

572
    public static void staticOneNullableArgThrows(@Nullable String s) {
573
      doThrow(s);
574
    }
575
  }
576

577
  public void testGoodClass() {
578
    shouldPass(new PassObject());
579
  }
580

581
  private static class FailOneArgDoesntThrowNPE extends PassObject {
582
    @Override
583
    public void oneArg(String s) {
584
      // Fail:  missing NPE for s
585
    }
586
  }
587

588
  public void testFailOneArgDoesntThrowNpe() {
589
    shouldFail(new FailOneArgDoesntThrowNPE());
590
  }
591

592
  private static class FailOneArgThrowsWrongType extends PassObject {
593
    @Override
594
    public void oneArg(String s) {
595
      doThrow(s); // Fail:  throwing non-NPE exception for null s
596
    }
597
  }
598

599
  public void testFailOneArgThrowsWrongType() {
600
    shouldFail(new FailOneArgThrowsWrongType());
601
  }
602

603
  private static class PassOneNullableArgThrowsNPE extends PassObject {
604
    @Override
605
    public void oneNullableArg(@Nullable String s) {
606
      checkNotNull(s); // ok to throw NPE
607
    }
608
  }
609

610
  public void testPassOneNullableArgThrowsNPE() {
611
    shouldPass(new PassOneNullableArgThrowsNPE());
612
  }
613

614
  private static class FailTwoArgsFirstArgDoesntThrowNPE extends PassObject {
615
    @Override
616
    public void twoArg(String s, Integer i) {
617
      // Fail: missing NPE for s
618
      i.intValue();
619
    }
620
  }
621

622
  public void testFailTwoArgsFirstArgDoesntThrowNPE() {
623
    shouldFail(new FailTwoArgsFirstArgDoesntThrowNPE());
624
  }
625

626
  private static class FailTwoArgsFirstArgThrowsWrongType extends PassObject {
627
    @Override
628
    public void twoArg(String s, Integer i) {
629
      doThrow(s); // Fail:  throwing non-NPE exception for null s
630
      i.intValue();
631
    }
632
  }
633

634
  public void testFailTwoArgsFirstArgThrowsWrongType() {
635
    shouldFail(new FailTwoArgsFirstArgThrowsWrongType());
636
  }
637

638
  private static class FailTwoArgsSecondArgDoesntThrowNPE extends PassObject {
639
    @Override
640
    public void twoArg(String s, Integer i) {
641
      checkNotNull(s);
642
      // Fail: missing NPE for i
643
    }
644
  }
645

646
  public void testFailTwoArgsSecondArgDoesntThrowNPE() {
647
    shouldFail(new FailTwoArgsSecondArgDoesntThrowNPE());
648
  }
649

650
  private static class FailTwoArgsSecondArgThrowsWrongType extends PassObject {
651
    @Override
652
    public void twoArg(String s, Integer i) {
653
      checkNotNull(s);
654
      doThrow(i); // Fail:  throwing non-NPE exception for null i
655
    }
656
  }
657

658
  public void testFailTwoArgsSecondArgThrowsWrongType() {
659
    shouldFail(new FailTwoArgsSecondArgThrowsWrongType());
660
  }
661

662
  private static class FailTwoMixedArgsFirstArgDoesntThrowNPE extends PassObject {
663
    @Override
664
    public void twoMixedArgs(String s, @Nullable Integer i) {
665
      // Fail: missing NPE for s
666
    }
667
  }
668

669
  public void testFailTwoMixedArgsFirstArgDoesntThrowNPE() {
670
    shouldFail(new FailTwoMixedArgsFirstArgDoesntThrowNPE());
671
  }
672

673
  private static class FailTwoMixedArgsFirstArgThrowsWrongType extends PassObject {
674
    @Override
675
    public void twoMixedArgs(String s, @Nullable Integer i) {
676
      doThrow(s); // Fail:  throwing non-NPE exception for null s
677
    }
678
  }
679

680
  public void testFailTwoMixedArgsFirstArgThrowsWrongType() {
681
    shouldFail(new FailTwoMixedArgsFirstArgThrowsWrongType());
682
  }
683

684
  private static class PassTwoMixedArgsNullableArgThrowsNPE extends PassObject {
685
    @Override
686
    public void twoMixedArgs(String s, @Nullable Integer i) {
687
      checkNotNull(s);
688
      i.intValue(); // ok to throw NPE?
689
    }
690
  }
691

692
  public void testPassTwoMixedArgsNullableArgThrowsNPE() {
693
    shouldPass(new PassTwoMixedArgsNullableArgThrowsNPE());
694
  }
695

696
  private static class PassTwoMixedArgSecondNullableArgThrowsOther extends PassObject {
697
    @Override
698
    public void twoMixedArgs(String s, @Nullable Integer i) {
699
      checkNotNull(s);
700
      doThrow(i); // ok to throw non-NPE exception for null i
701
    }
702
  }
703

704
  public void testPassTwoMixedArgSecondNullableArgThrowsOther() {
705
    shouldPass(new PassTwoMixedArgSecondNullableArgThrowsOther());
706
  }
707

708
  private static class FailTwoMixedArgsSecondArgDoesntThrowNPE extends PassObject {
709
    @Override
710
    public void twoMixedArgs(@Nullable Integer i, String s) {
711
      // Fail: missing NPE for null s
712
    }
713
  }
714

715
  public void testFailTwoMixedArgsSecondArgDoesntThrowNPE() {
716
    shouldFail(new FailTwoMixedArgsSecondArgDoesntThrowNPE());
717
  }
718

719
  private static class FailTwoMixedArgsSecondArgThrowsWrongType extends PassObject {
720
    @Override
721
    public void twoMixedArgs(@Nullable Integer i, String s) {
722
      doThrow(s); // Fail:  throwing non-NPE exception for null s
723
    }
724
  }
725

726
  public void testFailTwoMixedArgsSecondArgThrowsWrongType() {
727
    shouldFail(new FailTwoMixedArgsSecondArgThrowsWrongType());
728
  }
729

730
  private static class PassTwoNullableArgsFirstThrowsNPE extends PassObject {
731
    @Override
732
    public void twoNullableArgs(@Nullable String s, @Nullable Integer i) {
733
      checkNotNull(s); // ok to throw NPE?
734
    }
735
  }
736

737
  public void testPassTwoNullableArgsFirstThrowsNPE() {
738
    shouldPass(new PassTwoNullableArgsFirstThrowsNPE());
739
  }
740

741
  private static class PassTwoNullableArgsFirstThrowsOther extends PassObject {
742
    @Override
743
    public void twoNullableArgs(@Nullable String s, @Nullable Integer i) {
744
      doThrow(s); // ok to throw non-NPE exception for null s
745
    }
746
  }
747

748
  public void testPassTwoNullableArgsFirstThrowsOther() {
749
    shouldPass(new PassTwoNullableArgsFirstThrowsOther());
750
  }
751

752
  private static class PassTwoNullableArgsSecondThrowsNPE extends PassObject {
753
    @Override
754
    public void twoNullableArgs(@Nullable String s, @Nullable Integer i) {
755
      i.intValue(); // ok to throw NPE?
756
    }
757
  }
758

759
  public void testPassTwoNullableArgsSecondThrowsNPE() {
760
    shouldPass(new PassTwoNullableArgsSecondThrowsNPE());
761
  }
762

763
  private static class PassTwoNullableArgsSecondThrowsOther extends PassObject {
764
    @Override
765
    public void twoNullableArgs(@Nullable String s, @Nullable Integer i) {
766
      doThrow(i); // ok to throw non-NPE exception for null i
767
    }
768
  }
769

770
  public void testPassTwoNullableArgsSecondThrowsOther() {
771
    shouldPass(new PassTwoNullableArgsSecondThrowsOther());
772
  }
773

774
  private static class PassTwoNullableArgsNeitherThrowsAnything extends PassObject {
775
    @Override
776
    public void twoNullableArgs(@Nullable String s, @Nullable Integer i) {
777
      // ok to do nothing
778
    }
779
  }
780

781
  public void testPassTwoNullableArgsNeitherThrowsAnything() {
782
    shouldPass(new PassTwoNullableArgsNeitherThrowsAnything());
783
  }
784

785
  @SuppressWarnings("unused") // for NullPointerTester
786
  private abstract static class BaseClassThatFailsToThrow {
787
    public void oneArg(String s) {}
788
  }
789

790
  private static class SubclassWithBadSuperclass extends BaseClassThatFailsToThrow {}
791

792
  public void testSubclassWithBadSuperclass() {
793
    shouldFail(new SubclassWithBadSuperclass());
794
  }
795

796
  @SuppressWarnings("unused") // for NullPointerTester
797
  private abstract static class BaseClassThatFailsToThrowForPackagePrivate {
798
    void packagePrivateOneArg(String s) {}
799
  }
800

801
  private static class SubclassWithBadSuperclassForPackagePrivate
802
      extends BaseClassThatFailsToThrowForPackagePrivate {}
803

804
  public void testSubclassWithBadSuperclassForPackagePrivateMethod() {
805
    shouldFail(new SubclassWithBadSuperclassForPackagePrivate(), Visibility.PACKAGE);
806
  }
807

808
  @SuppressWarnings("unused") // for NullPointerTester
809
  private abstract static class BaseClassThatFailsToThrowForProtected {
810
    protected void protectedOneArg(String s) {}
811
  }
812

813
  private static class SubclassWithBadSuperclassForProtected
814
      extends BaseClassThatFailsToThrowForProtected {}
815

816
  public void testSubclassWithBadSuperclassForPackageProtectedMethod() {
817
    shouldFail(new SubclassWithBadSuperclassForProtected(), Visibility.PROTECTED);
818
  }
819

820
  private static class SubclassThatOverridesBadSuperclassMethod extends BaseClassThatFailsToThrow {
821
    @Override
822
    public void oneArg(@Nullable String s) {}
823
  }
824

825
  public void testSubclassThatOverridesBadSuperclassMethod() {
826
    shouldPass(new SubclassThatOverridesBadSuperclassMethod());
827
  }
828

829
  @SuppressWarnings("unused") // for NullPointerTester
830
  private static class SubclassOverridesTheWrongMethod extends BaseClassThatFailsToThrow {
831
    public void oneArg(@Nullable CharSequence s) {}
832
  }
833

834
  public void testSubclassOverridesTheWrongMethod() {
835
    shouldFail(new SubclassOverridesTheWrongMethod());
836
  }
837

838
  @SuppressWarnings("unused") // for NullPointerTester
839
  private static class ClassThatFailsToThrowForStatic {
840
    static void staticOneArg(String s) {}
841
  }
842

843
  public void testClassThatFailsToThrowForStatic() {
844
    shouldFail(ClassThatFailsToThrowForStatic.class);
845
  }
846

847
  private static class SubclassThatFailsToThrowForStatic extends ClassThatFailsToThrowForStatic {}
848

849
  public void testSubclassThatFailsToThrowForStatic() {
850
    shouldFail(SubclassThatFailsToThrowForStatic.class);
851
  }
852

853
  private static class SubclassThatTriesToOverrideBadStaticMethod
854
      extends ClassThatFailsToThrowForStatic {
855
    static void staticOneArg(String unused) {}
856
  }
857

858
  public void testSubclassThatTriesToOverrideBadStaticMethod() {
859
    shouldFail(SubclassThatTriesToOverrideBadStaticMethod.class);
860
  }
861

862
  private static final class HardToCreate {
863
    private HardToCreate(String unused) {}
864
  }
865

866
  @SuppressWarnings("unused") // used by reflection
867
  private static class CanCreateDefault {
868
    public void foo(@Nullable HardToCreate ignored, String required) {
869
      checkNotNull(required);
870
    }
871
  }
872

873
  public void testCanCreateDefault() {
874
    shouldPass(new CanCreateDefault());
875
  }
876

877
  @SuppressWarnings("unused") // used by reflection
878
  private static class CannotCreateDefault {
879
    public void foo(HardToCreate ignored, String required) {
880
      checkNotNull(ignored);
881
      checkNotNull(required);
882
    }
883
  }
884

885
  public void testCannotCreateDefault() {
886
    shouldFail(new CannotCreateDefault());
887
  }
888

889
  private static void shouldPass(Object instance, Visibility visibility) {
890
    new NullPointerTester().testInstanceMethods(instance, visibility);
891
  }
892

893
  private static void shouldPass(Object instance) {
894
    shouldPass(instance, Visibility.PACKAGE);
895
    shouldPass(instance, Visibility.PROTECTED);
896
    shouldPass(instance, Visibility.PUBLIC);
897
  }
898

899
  // TODO(cpovirk): eliminate surprising Object/Class overloading of shouldFail
900

901
  private static void shouldFail(Object instance, Visibility visibility) {
902
    try {
903
      new NullPointerTester().testInstanceMethods(instance, visibility);
904
    } catch (AssertionError expected) {
905
      return;
906
    }
907
    fail("Should detect problem in " + instance.getClass().getSimpleName());
908
  }
909

910
  private static void shouldFail(Object instance) {
911
    shouldFail(instance, Visibility.PACKAGE);
912
    shouldFail(instance, Visibility.PROTECTED);
913
    shouldFail(instance, Visibility.PUBLIC);
914
  }
915

916
  private static void shouldFail(Class<?> cls, Visibility visibility) {
917
    try {
918
      new NullPointerTester().testStaticMethods(cls, visibility);
919
    } catch (AssertionError expected) {
920
      return;
921
    }
922
    fail("Should detect problem in " + cls.getSimpleName());
923
  }
924

925
  private static void shouldFail(Class<?> cls) {
926
    shouldFail(cls, Visibility.PACKAGE);
927
  }
928

929
  @SuppressWarnings("unused") // used by reflection
930
  private static class PrivateClassWithPrivateConstructor {
931
    private PrivateClassWithPrivateConstructor(@Nullable Integer argument) {}
932
  }
933

934
  public void testPrivateClass() {
935
    NullPointerTester tester = new NullPointerTester();
936
    for (Constructor<?> constructor :
937
        PrivateClassWithPrivateConstructor.class.getDeclaredConstructors()) {
938
      tester.testConstructor(constructor);
939
    }
940
  }
941

942
  private interface Foo<T> {
943
    void doSomething(T bar, Integer baz);
944
  }
945

946
  private static class StringFoo implements Foo<String> {
947

948
    @Override
949
    public void doSomething(String bar, Integer baz) {
950
      checkNotNull(bar);
951
      checkNotNull(baz);
952
    }
953
  }
954

955
  public void testBridgeMethodIgnored() {
956
    new NullPointerTester().testAllPublicInstanceMethods(new StringFoo());
957
  }
958

959
  private abstract static class DefaultValueChecker {
960

961
    private final Map<Integer, Object> arguments = Maps.newHashMap();
962

963
    @CanIgnoreReturnValue
964
    final DefaultValueChecker runTester() {
965
      new NullPointerTester().testInstanceMethods(this, Visibility.PACKAGE);
966
      return this;
967
    }
968

969
    final void assertNonNullValues(Object... expectedValues) {
970
      assertEquals(expectedValues.length, arguments.size());
971
      for (int i = 0; i < expectedValues.length; i++) {
972
        assertEquals("Default value for parameter #" + i, expectedValues[i], arguments.get(i));
973
      }
974
    }
975

976
    final Object getDefaultParameterValue(int position) {
977
      return arguments.get(position);
978
    }
979

980
    final void calledWith(Object... args) {
981
      for (int i = 0; i < args.length; i++) {
982
        if (args[i] != null) {
983
          arguments.put(i, args[i]);
984
        }
985
      }
986
      for (Object arg : args) {
987
        checkNotNull(arg); // to fulfill null check
988
      }
989
    }
990
  }
991

992
  private enum Gender {
993
    MALE,
994
    FEMALE
995
  }
996

997
  private static class AllDefaultValuesChecker extends DefaultValueChecker {
998

999
    @SuppressWarnings("unused") // called by NullPointerTester
1000
    public void checkDefaultValuesForTheseTypes(
1001
        Gender gender,
1002
        Integer integer,
1003
        int i,
1004
        String string,
1005
        CharSequence charSequence,
1006
        List<String> list,
1007
        ImmutableList<Integer> immutableList,
1008
        Map<String, Integer> map,
1009
        ImmutableMap<String, String> immutableMap,
1010
        Set<String> set,
1011
        ImmutableSet<Integer> immutableSet,
1012
        SortedSet<Number> sortedSet,
1013
        ImmutableSortedSet<Number> immutableSortedSet,
1014
        Multiset<String> multiset,
1015
        ImmutableMultiset<Integer> immutableMultiset,
1016
        Multimap<String, Integer> multimap,
1017
        ImmutableMultimap<String, Integer> immutableMultimap,
1018
        Table<String, Integer, Exception> table,
1019
        ImmutableTable<Integer, String, Exception> immutableTable) {
1020
      calledWith(
1021
          gender,
1022
          integer,
1023
          i,
1024
          string,
1025
          charSequence,
1026
          list,
1027
          immutableList,
1028
          map,
1029
          immutableMap,
1030
          set,
1031
          immutableSet,
1032
          sortedSet,
1033
          immutableSortedSet,
1034
          multiset,
1035
          immutableMultiset,
1036
          multimap,
1037
          immutableMultimap,
1038
          table,
1039
          immutableTable);
1040
    }
1041

1042
    final void check() {
1043
      runTester()
1044
          .assertNonNullValues(
1045
              Gender.MALE,
1046
              Integer.valueOf(0),
1047
              0,
1048
              "",
1049
              "",
1050
              ImmutableList.of(),
1051
              ImmutableList.of(),
1052
              ImmutableMap.of(),
1053
              ImmutableMap.of(),
1054
              ImmutableSet.of(),
1055
              ImmutableSet.of(),
1056
              ImmutableSortedSet.of(),
1057
              ImmutableSortedSet.of(),
1058
              ImmutableMultiset.of(),
1059
              ImmutableMultiset.of(),
1060
              ImmutableMultimap.of(),
1061
              ImmutableMultimap.of(),
1062
              ImmutableTable.of(),
1063
              ImmutableTable.of());
1064
    }
1065
  }
1066

1067
  public void testDefaultValues() {
1068
    new AllDefaultValuesChecker().check();
1069
  }
1070

1071
  private static class ObjectArrayDefaultValueChecker extends DefaultValueChecker {
1072

1073
    @SuppressWarnings("unused") // called by NullPointerTester
1074
    public void checkArray(Object[] array, String s) {
1075
      calledWith(array, s);
1076
    }
1077

1078
    void check() {
1079
      runTester();
1080
      Object[] defaultArray = (Object[]) getDefaultParameterValue(0);
1081
      assertThat(defaultArray).isEmpty();
1082
    }
1083
  }
1084

1085
  public void testObjectArrayDefaultValue() {
1086
    new ObjectArrayDefaultValueChecker().check();
1087
  }
1088

1089
  private static class StringArrayDefaultValueChecker extends DefaultValueChecker {
1090

1091
    @SuppressWarnings("unused") // called by NullPointerTester
1092
    public void checkArray(String[] array, String s) {
1093
      calledWith(array, s);
1094
    }
1095

1096
    void check() {
1097
      runTester();
1098
      String[] defaultArray = (String[]) getDefaultParameterValue(0);
1099
      assertThat(defaultArray).isEmpty();
1100
    }
1101
  }
1102

1103
  public void testStringArrayDefaultValue() {
1104
    new StringArrayDefaultValueChecker().check();
1105
  }
1106

1107
  private static class IntArrayDefaultValueChecker extends DefaultValueChecker {
1108

1109
    @SuppressWarnings("unused") // called by NullPointerTester
1110
    public void checkArray(int[] array, String s) {
1111
      calledWith(array, s);
1112
    }
1113

1114
    void check() {
1115
      runTester();
1116
      int[] defaultArray = (int[]) getDefaultParameterValue(0);
1117
      assertEquals(0, defaultArray.length);
1118
    }
1119
  }
1120

1121
  public void testIntArrayDefaultValue() {
1122
    new IntArrayDefaultValueChecker().check();
1123
  }
1124

1125
  private enum EmptyEnum {}
1126

1127
  private static class EmptyEnumDefaultValueChecker extends DefaultValueChecker {
1128

1129
    @SuppressWarnings("unused") // called by NullPointerTester
1130
    public void checkArray(EmptyEnum object, String s) {
1131
      calledWith(object, s);
1132
    }
1133

1134
    void check() {
1135
      try {
1136
        runTester();
1137
      } catch (AssertionError expected) {
1138
        return;
1139
      }
1140
      fail("Should have failed because enum has no constant");
1141
    }
1142
  }
1143

1144
  public void testEmptyEnumDefaultValue() {
1145
    new EmptyEnumDefaultValueChecker().check();
1146
  }
1147

1148
  private static class GenericClassTypeDefaultValueChecker extends DefaultValueChecker {
1149

1150
    @SuppressWarnings("unused") // called by NullPointerTester
1151
    public void checkArray(Class<? extends List<?>> cls, String s) {
1152
      calledWith(cls, s);
1153
    }
1154

1155
    void check() {
1156
      runTester();
1157
      Class<?> defaultClass = (Class<?>) getDefaultParameterValue(0);
1158
      assertEquals(List.class, defaultClass);
1159
    }
1160
  }
1161

1162
  public void testGenericClassDefaultValue() {
1163
    new GenericClassTypeDefaultValueChecker().check();
1164
  }
1165

1166
  private static class NonGenericClassTypeDefaultValueChecker extends DefaultValueChecker {
1167

1168
    @SuppressWarnings("unused") // called by NullPointerTester
1169
    public void checkArray(@SuppressWarnings("rawtypes") Class cls, String s) {
1170
      calledWith(cls, s);
1171
    }
1172

1173
    void check() {
1174
      runTester();
1175
      Class<?> defaultClass = (Class<?>) getDefaultParameterValue(0);
1176
      assertEquals(Object.class, defaultClass);
1177
    }
1178
  }
1179

1180
  public void testNonGenericClassDefaultValue() {
1181
    new NonGenericClassTypeDefaultValueChecker().check();
1182
  }
1183

1184
  private static class GenericTypeTokenDefaultValueChecker extends DefaultValueChecker {
1185

1186
    @SuppressWarnings("unused") // called by NullPointerTester
1187
    public void checkArray(TypeToken<? extends List<? super Number>> type, String s) {
1188
      calledWith(type, s);
1189
    }
1190

1191
    void check() {
1192
      runTester();
1193
      TypeToken<?> defaultType = (TypeToken<?>) getDefaultParameterValue(0);
1194
      assertTrue(new TypeToken<List<? super Number>>() {}.isSupertypeOf(defaultType));
1195
    }
1196
  }
1197

1198
  public void testGenericTypeTokenDefaultValue() {
1199
    new GenericTypeTokenDefaultValueChecker().check();
1200
  }
1201

1202
  private static class NonGenericTypeTokenDefaultValueChecker extends DefaultValueChecker {
1203

1204
    @SuppressWarnings("unused") // called by NullPointerTester
1205
    public void checkArray(@SuppressWarnings("rawtypes") TypeToken type, String s) {
1206
      calledWith(type, s);
1207
    }
1208

1209
    void check() {
1210
      runTester();
1211
      TypeToken<?> defaultType = (TypeToken<?>) getDefaultParameterValue(0);
1212
      assertEquals(new TypeToken<Object>() {}, defaultType);
1213
    }
1214
  }
1215

1216
  public void testNonGenericTypeTokenDefaultValue() {
1217
    new NonGenericTypeTokenDefaultValueChecker().check();
1218
  }
1219

1220
  private interface FromTo<F, T> extends Function<F, T> {}
1221

1222
  private static class GenericInterfaceDefaultValueChecker extends DefaultValueChecker {
1223

1224
    @SuppressWarnings("unused") // called by NullPointerTester
1225
    public void checkArray(FromTo<String, Integer> f, String s) {
1226
      calledWith(f, s);
1227
    }
1228

1229
    void check() {
1230
      runTester();
1231
      FromTo<?, ?> defaultFunction = (FromTo<?, ?>) getDefaultParameterValue(0);
1232
      assertEquals(0, defaultFunction.apply(null));
1233
    }
1234
  }
1235

1236
  public void testGenericInterfaceDefaultValue() {
1237
    new GenericInterfaceDefaultValueChecker().check();
1238
  }
1239

1240
  private interface NullRejectingFromTo<F, T> extends Function<F, T> {
1241
    @Override
1242
    public abstract T apply(F from);
1243
  }
1244

1245
  private static class NullRejectingInterfaceDefaultValueChecker extends DefaultValueChecker {
1246

1247
    @SuppressWarnings("unused") // called by NullPointerTester
1248
    public void checkArray(NullRejectingFromTo<String, Integer> f, String s) {
1249
      calledWith(f, s);
1250
    }
1251

1252
    void check() {
1253
      runTester();
1254
      NullRejectingFromTo<?, ?> defaultFunction =
1255
          (NullRejectingFromTo<?, ?>) getDefaultParameterValue(0);
1256
      assertNotNull(defaultFunction);
1257
      try {
1258
        defaultFunction.apply(null);
1259
        fail("Proxy Should have rejected null");
1260
      } catch (NullPointerException expected) {
1261
      }
1262
    }
1263
  }
1264

1265
  public void testNullRejectingInterfaceDefaultValue() {
1266
    new NullRejectingInterfaceDefaultValueChecker().check();
1267
  }
1268

1269
  private static class MultipleInterfacesDefaultValueChecker extends DefaultValueChecker {
1270

1271
    @SuppressWarnings("unused") // called by NullPointerTester
1272
    public <T extends FromTo<String, Integer> & Supplier<Long>> void checkArray(T f, String s) {
1273
      calledWith(f, s);
1274
    }
1275

1276
    void check() {
1277
      runTester();
1278
      FromTo<?, ?> defaultFunction = (FromTo<?, ?>) getDefaultParameterValue(0);
1279
      assertEquals(0, defaultFunction.apply(null));
1280
      Supplier<?> defaultSupplier = (Supplier<?>) defaultFunction;
1281
      assertEquals(Long.valueOf(0), defaultSupplier.get());
1282
    }
1283
  }
1284

1285
  public void testMultipleInterfacesDefaultValue() {
1286
    new MultipleInterfacesDefaultValueChecker().check();
1287
  }
1288

1289
  private static class GenericInterface2DefaultValueChecker extends DefaultValueChecker {
1290

1291
    @SuppressWarnings("unused") // called by NullPointerTester
1292
    public void checkArray(FromTo<String, FromTo<Integer, String>> f, String s) {
1293
      calledWith(f, s);
1294
    }
1295

1296
    void check() {
1297
      runTester();
1298
      FromTo<?, ?> defaultFunction = (FromTo<?, ?>) getDefaultParameterValue(0);
1299
      FromTo<?, ?> returnValue = (FromTo<?, ?>) defaultFunction.apply(null);
1300
      assertEquals("", returnValue.apply(null));
1301
    }
1302
  }
1303

1304
  public void testGenericInterfaceReturnedByGenericMethod() {
1305
    new GenericInterface2DefaultValueChecker().check();
1306
  }
1307

1308
  private abstract static class AbstractGenericDefaultValueChecker<T> extends DefaultValueChecker {
1309

1310
    @SuppressWarnings("unused") // called by NullPointerTester
1311
    public void checkGeneric(T value, String s) {
1312
      calledWith(value, s);
1313
    }
1314
  }
1315

1316
  private static class GenericDefaultValueResolvedToStringChecker
1317
      extends AbstractGenericDefaultValueChecker<String> {
1318
    void check() {
1319
      runTester();
1320
      assertEquals("", getDefaultParameterValue(0));
1321
    }
1322
  }
1323

1324
  public void testGenericTypeResolvedForDefaultValue() {
1325
    new GenericDefaultValueResolvedToStringChecker().check();
1326
  }
1327

1328
  private abstract static class AbstractGenericDefaultValueForPackagePrivateMethodChecker<T>
1329
      extends DefaultValueChecker {
1330

1331
    @SuppressWarnings("unused") // called by NullPointerTester
1332
    void checkGeneric(T value, String s) {
1333
      calledWith(value, s);
1334
    }
1335
  }
1336

1337
  private static class DefaultValueForPackagePrivateMethodResolvedToStringChecker
1338
      extends AbstractGenericDefaultValueForPackagePrivateMethodChecker<String> {
1339
    void check() {
1340
      runTester();
1341
      assertEquals("", getDefaultParameterValue(0));
1342
    }
1343
  }
1344

1345
  public void testDefaultValueResolvedForPackagePrivateMethod() {
1346
    new DefaultValueForPackagePrivateMethodResolvedToStringChecker().check();
1347
  }
1348

1349
  private static class ConverterDefaultValueChecker extends DefaultValueChecker {
1350

1351
    @SuppressWarnings("unused") // called by NullPointerTester
1352
    public void checkArray(Converter<String, Integer> c, String s) {
1353
      calledWith(c, s);
1354
    }
1355

1356
    void check() {
1357
      runTester();
1358
      @SuppressWarnings("unchecked") // We are checking it anyway
1359
      Converter<String, Integer> defaultConverter =
1360
          (Converter<String, Integer>) getDefaultParameterValue(0);
1361
      assertEquals(Integer.valueOf(0), defaultConverter.convert("anything"));
1362
      assertEquals("", defaultConverter.reverse().convert(123));
1363
      assertNull(defaultConverter.convert(null));
1364
      assertNull(defaultConverter.reverse().convert(null));
1365
    }
1366
  }
1367

1368
  public void testConverterDefaultValue() {
1369
    new ConverterDefaultValueChecker().check();
1370
  }
1371

1372
  private static class VisibilityMethods {
1373

1374
    @SuppressWarnings("unused") // Called by reflection
1375
    private void privateMethod() {}
1376

1377
    @SuppressWarnings("unused") // Called by reflection
1378
    void packagePrivateMethod() {}
1379

1380
    @SuppressWarnings("unused") // Called by reflection
1381
    protected void protectedMethod() {}
1382

1383
    @SuppressWarnings("unused") // Called by reflection
1384
    public void publicMethod() {}
1385
  }
1386

1387
  public void testVisibility_public() throws Exception {
1388
    assertFalse(
1389
        Visibility.PUBLIC.isVisible(VisibilityMethods.class.getDeclaredMethod("privateMethod")));
1390
    assertFalse(
1391
        Visibility.PUBLIC.isVisible(
1392
            VisibilityMethods.class.getDeclaredMethod("packagePrivateMethod")));
1393
    assertFalse(
1394
        Visibility.PUBLIC.isVisible(VisibilityMethods.class.getDeclaredMethod("protectedMethod")));
1395
    assertTrue(
1396
        Visibility.PUBLIC.isVisible(VisibilityMethods.class.getDeclaredMethod("publicMethod")));
1397
  }
1398

1399
  public void testVisibility_protected() throws Exception {
1400
    assertFalse(
1401
        Visibility.PROTECTED.isVisible(VisibilityMethods.class.getDeclaredMethod("privateMethod")));
1402
    assertFalse(
1403
        Visibility.PROTECTED.isVisible(
1404
            VisibilityMethods.class.getDeclaredMethod("packagePrivateMethod")));
1405
    assertTrue(
1406
        Visibility.PROTECTED.isVisible(
1407
            VisibilityMethods.class.getDeclaredMethod("protectedMethod")));
1408
    assertTrue(
1409
        Visibility.PROTECTED.isVisible(VisibilityMethods.class.getDeclaredMethod("publicMethod")));
1410
  }
1411

1412
  public void testVisibility_package() throws Exception {
1413
    assertFalse(
1414
        Visibility.PACKAGE.isVisible(VisibilityMethods.class.getDeclaredMethod("privateMethod")));
1415
    assertTrue(
1416
        Visibility.PACKAGE.isVisible(
1417
            VisibilityMethods.class.getDeclaredMethod("packagePrivateMethod")));
1418
    assertTrue(
1419
        Visibility.PACKAGE.isVisible(VisibilityMethods.class.getDeclaredMethod("protectedMethod")));
1420
    assertTrue(
1421
        Visibility.PACKAGE.isVisible(VisibilityMethods.class.getDeclaredMethod("publicMethod")));
1422
  }
1423

1424
  private class Inner {
1425
    public Inner(String s) {
1426
      checkNotNull(s);
1427
    }
1428
  }
1429

1430
  public void testNonStaticInnerClass() {
1431
    IllegalArgumentException expected =
1432
        assertThrows(
1433
            IllegalArgumentException.class,
1434
            () -> new NullPointerTester().testAllPublicConstructors(Inner.class));
1435
    assertThat(expected.getMessage()).contains("inner class");
1436
  }
1437

1438
  private static String rootLocaleFormat(String format, Object... args) {
1439
    return String.format(Locale.ROOT, format, args);
1440
  }
1441

1442
  static class OverridesEquals {
1443
    @SuppressWarnings("EqualsHashCode")
1444
    @Override
1445
    public boolean equals(@Nullable Object o) {
1446
      return true;
1447
    }
1448
  }
1449

1450
  static class DoesNotOverrideEquals {
1451
    public boolean equals(Object a, Object b) {
1452
      return true;
1453
    }
1454
  }
1455

1456
  public void testEqualsMethod() {
1457
    shouldPass(new OverridesEquals());
1458
    shouldFail(new DoesNotOverrideEquals());
1459
  }
1460

1461
  private static final class FailOnOneOfTwoConstructors {
1462
    @SuppressWarnings("unused") // Called by reflection
1463
    public FailOnOneOfTwoConstructors(String s) {}
1464

1465
    @SuppressWarnings("unused") // Called by reflection
1466
    public FailOnOneOfTwoConstructors(Object o) {
1467
      checkNotNull(o);
1468
    }
1469
  }
1470

1471
  public void testConstructor_ignored_shouldPass() throws Exception {
1472
    new NullPointerTester()
1473
        .ignore(FailOnOneOfTwoConstructors.class.getDeclaredConstructor(String.class))
1474
        .testAllPublicConstructors(FailOnOneOfTwoConstructors.class);
1475
  }
1476

1477
  public void testConstructor_shouldFail() throws Exception {
1478
    try {
1479
      new NullPointerTester().testAllPublicConstructors(FailOnOneOfTwoConstructors.class);
1480
    } catch (AssertionError expected) {
1481
      return;
1482
    }
1483
    fail("Should detect problem in " + FailOnOneOfTwoConstructors.class.getSimpleName());
1484
  }
1485

1486
  public static class NullBounds<T extends @Nullable Object, U extends T, X> {
1487
    boolean xWasCalled;
1488

1489
    @SuppressWarnings("unused") // Called by reflection
1490
    public void x(X x) {
1491
      xWasCalled = true;
1492
      checkNotNull(x);
1493
    }
1494

1495
    @SuppressWarnings("unused") // Called by reflection
1496
    public void t(T t) {
1497
      fail("Method with parameter <T extends @Nullable Object> should not be called");
1498
    }
1499

1500
    @SuppressWarnings("unused") // Called by reflection
1501
    public void u(U u) {
1502
      fail(
1503
          "Method with parameter <U extends T> where <T extends @Nullable Object> should not be"
1504
              + " called");
1505
    }
1506

1507
    @SuppressWarnings("unused") // Called by reflection
1508
    public <A extends @Nullable Object> void a(A a) {
1509
      fail("Method with parameter <A extends @Nullable Object> should not be called");
1510
    }
1511

1512
    @SuppressWarnings("unused") // Called by reflection
1513
    public <A extends B, B extends @Nullable Object> void b(A a) {
1514
      fail(
1515
          "Method with parameter <A extends B> where <B extends @Nullable Object> should not be"
1516
              + " called");
1517
    }
1518
  }
1519

1520
  public void testNullBounds() {
1521
    // NullBounds has methods whose parameters are type variables that have
1522
    // "extends @Nullable Object" as a bound. This test ensures that NullPointerTester considers
1523
    // those parameters to be @Nullable, so it won't call the methods.
1524
    NullBounds<?, ?, ?> nullBounds = new NullBounds<>();
1525
    new NullPointerTester().testAllPublicInstanceMethods(nullBounds);
1526
    assertThat(nullBounds.xWasCalled).isTrue();
1527
  }
1528
}
1529

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.