Reviewed By: jeremydubreil Differential Revision: D2747240 fb-gh-sync-id: 512cf6dmaster
							parent
							
								
									3dcd6490c2
								
							
						
					
					
						commit
						14e934205f
					
				| @ -0,0 +1,74 @@ | |||||||
|  | /* | ||||||
|  |  * Copyright (c) 2016 - present Facebook, Inc. | ||||||
|  |  * All rights reserved. | ||||||
|  |  * | ||||||
|  |  * This source code is licensed under the BSD style license found in the | ||||||
|  |  * LICENSE file in the root directory of this source tree. An additional grant | ||||||
|  |  * of patent rights can be found in the PATENTS file in the same directory. | ||||||
|  |  */ | ||||||
|  | 
 | ||||||
|  | package codetoanalyze.java.infer; | ||||||
|  | 
 | ||||||
|  | public class DynamicDispatch { | ||||||
|  | 
 | ||||||
|  |    static interface Interface { | ||||||
|  |     public Object foo(); | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   static class Impl implements Interface { | ||||||
|  |     @Override public Object foo() { | ||||||
|  |       return null; | ||||||
|  |     } | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   static void interfaceShouldNotCauseFalseNegativeEasy() { | ||||||
|  |     Interface i = new Impl(); | ||||||
|  |     // should be a warning since Impl's implementation of foo returns null
 | ||||||
|  |     i.foo().toString(); | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   // TODO: this test currently fails, but will pass with handling of dynamic dispatch
 | ||||||
|  |   static void interfaceShouldNotCauseFalseNegativeHard(Interface i) { | ||||||
|  |     // should be a warning since Impl's implementation of foo returns null
 | ||||||
|  |     i.foo().toString(); | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   static class Supertype { | ||||||
|  |     Object foo() { | ||||||
|  |       return new Object(); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     Object bar() { | ||||||
|  |       return null; | ||||||
|  |     } | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   static class Subtype extends Supertype { | ||||||
|  |     @Override Object foo() { | ||||||
|  |       return null; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     @Override Object bar() { | ||||||
|  |       return new Object(); | ||||||
|  |     } | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   static void dynamicDispatchShouldNotCauseFalseNegativeEasy() { | ||||||
|  |     Supertype o = new Subtype(); | ||||||
|  |     // should report a warning because we know the dynamic type of o is Subtype
 | ||||||
|  |     o.foo().toString(); | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   static void dynamicDispatchShouldNotCauseFalsePositiveEasy() { | ||||||
|  |     Supertype o = new Subtype(); | ||||||
|  |     // should not report a warning because we know the dynamic type of o is Subtype
 | ||||||
|  |     o.bar().toString(); | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   // TODO: this test currently fails, but will pass with handling of dynamic dispatch
 | ||||||
|  |   static void dynamicDispatchShouldNotCauseFalseNegativeHardTODO(Supertype o) { | ||||||
|  |     // should report a warning because Subtype's implementation of foo() can return null;
 | ||||||
|  |     o.foo().toString(); | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  | } | ||||||
| @ -0,0 +1,59 @@ | |||||||
|  | /* | ||||||
|  |  * Copyright (c) 2016 - present Facebook, Inc. | ||||||
|  |  * All rights reserved. | ||||||
|  |  * | ||||||
|  |  * This source code is licensed under the BSD style license found in the | ||||||
|  |  * LICENSE file in the root directory of this source tree. An additional grant | ||||||
|  |  * of patent rights can be found in the PATENTS file in the same directory. | ||||||
|  |  */ | ||||||
|  | 
 | ||||||
|  | package endtoend.java.infer; | ||||||
|  | 
 | ||||||
|  | import static org.hamcrest.MatcherAssert.assertThat; | ||||||
|  | import static utils.matchers.ResultContainsExactly.containsExactly; | ||||||
|  | 
 | ||||||
|  | import org.junit.BeforeClass; | ||||||
|  | import org.junit.Test; | ||||||
|  | 
 | ||||||
|  | import java.io.IOException; | ||||||
|  | 
 | ||||||
|  | import utils.InferException; | ||||||
|  | import utils.InferResults; | ||||||
|  | 
 | ||||||
|  | public class DynamicDispatchTest { | ||||||
|  | 
 | ||||||
|  |   public static final String DynamicDispatchFile = | ||||||
|  |       "infer/tests/codetoanalyze/java/infer/DynamicDispatch.java"; | ||||||
|  | 
 | ||||||
|  |   public static final String NULL_DEREFERENCE = "NULL_DEREFERENCE"; | ||||||
|  | 
 | ||||||
|  |   private static InferResults inferResults; | ||||||
|  | 
 | ||||||
|  |   @BeforeClass | ||||||
|  |   public static void loadResults() throws InterruptedException, IOException { | ||||||
|  |     inferResults = InferResults.loadInferResults(DynamicDispatchTest.class, DynamicDispatchFile); | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   @Test | ||||||
|  |   public void matchErrors() | ||||||
|  |       throws InterruptedException, IOException, InferException { | ||||||
|  |     String[] methods = { | ||||||
|  |       "interfaceShouldNotCauseFalseNegativeEasy", | ||||||
|  |       "dynamicDispatchShouldNotCauseFalseNegativeEasy", | ||||||
|  |       "interfaceShouldNotCauseFalseNegativeHard" | ||||||
|  |       // TODO: add dynamic dispatch support to make these tests work
 | ||||||
|  |       // "dynamicDispatchShouldNotCauseFalseNegativeHardTODO"
 | ||||||
|  |     }; | ||||||
|  | 
 | ||||||
|  |     assertThat( | ||||||
|  |         "Results should contain null dereference", | ||||||
|  |         inferResults, | ||||||
|  |         containsExactly( | ||||||
|  |             NULL_DEREFERENCE, | ||||||
|  |             DynamicDispatchFile, | ||||||
|  |             methods | ||||||
|  |         ) | ||||||
|  |     ); | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  | } | ||||||
					Loading…
					
					
				
		Reference in new issue