-
Notifications
You must be signed in to change notification settings - Fork 437
Add RLC-only SideEffectFree stubs and tests #7609
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Changes from all commits
77d5a28
e1d5221
22fac31
d72e909
4abfe12
5d5fd21
e8970a4
2806c28
e910131
d8032c6
6b44afe
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,19 @@ | ||
| package java.lang; | ||
|
|
||
| import org.checkerframework.checker.lock.qual.GuardSatisfied; | ||
| import org.checkerframework.dataflow.qual.SideEffectFree; | ||
|
|
||
| public interface AutoCloseable { | ||
| @SideEffectFree | ||
| void close(@GuardSatisfied AutoCloseable this) throws Exception; | ||
| } | ||
|
|
||
| package java.io; | ||
|
|
||
| import org.checkerframework.checker.lock.qual.GuardSatisfied; | ||
| import org.checkerframework.dataflow.qual.SideEffectFree; | ||
|
|
||
| public interface Closeable extends AutoCloseable { | ||
| @SideEffectFree | ||
| public void close(@GuardSatisfied Closeable this) throws IOException; | ||
| } | ||
|
iamsanjaymalakar marked this conversation as resolved.
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,25 @@ | ||
| // RLC uses Called Methods facts to remember that a resource has already been closed. | ||
| // This test checks that the RLC-specific SideEffectFree stub for AutoCloseable.close() | ||
| // preserves those facts across another close call in the same destructor, rather than | ||
| // conservatively forgetting them after the first invocation. | ||
|
|
||
| import org.checkerframework.checker.calledmethods.qual.EnsuresCalledMethods; | ||
| import org.checkerframework.checker.mustcall.qual.Owning; | ||
|
|
||
| class AutoCloseableClose implements AutoCloseable { | ||
| private @Owning AutoCloseable first = new AutoCloseableResource(); | ||
| private @Owning AutoCloseable second = new AutoCloseableResource(); | ||
|
|
||
| @Override | ||
| @EnsuresCalledMethods( | ||
| value = {"this.first", "this.second"}, | ||
| methods = "close") | ||
| public void close() { | ||
| try { | ||
| first.close(); | ||
| second.close(); | ||
| } catch (Exception e) { | ||
| throw new AssertionError(e); | ||
| } | ||
| } | ||
|
iamsanjaymalakar marked this conversation as resolved.
|
||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,29 @@ | ||
| // RLC uses Called Methods facts to remember that a resource has already been closed. | ||
| // This test checks that the RLC-specific SideEffectFree stub for Closeable.close() | ||
| // preserves those facts across another close call in the same destructor, rather than | ||
| // conservatively forgetting them after the first invocation. | ||
|
|
||
| import java.io.Closeable; | ||
| import org.checkerframework.checker.calledmethods.qual.EnsuresCalledMethods; | ||
| import org.checkerframework.checker.mustcall.qual.Owning; | ||
|
|
||
| class CloseableClose implements Closeable { | ||
| private @Owning Closeable first = new CloseableResource(); | ||
| private @Owning Closeable second = new CloseableResource(); | ||
|
|
||
| @Override | ||
| @EnsuresCalledMethods( | ||
| value = {"this.first", "this.second"}, | ||
| methods = "close") | ||
| public void close() { | ||
| try { | ||
| try { | ||
| first.close(); | ||
| } catch (Exception ignored) { | ||
| } | ||
| second.close(); | ||
| } catch (Exception e) { | ||
| throw new AssertionError(e); | ||
| } | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,14 @@ | ||
| // Class representing reources that implements Closeable and Autocloseable to be used by other tests | ||
| // in this directory. | ||
|
Comment on lines
+1
to
+2
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Fix typos in the header comment. "reources" → "resources"; "Autocloseable" → "AutoCloseable". ✏️ Proposed fix-// Class representing reources that implements Closeable and Autocloseable to be used by other tests
-// in this directory.
+// Classes representing resources that implement Closeable and AutoCloseable, to be used by other
+// tests in this directory.🤖 Prompt for AI Agents |
||
|
|
||
| import java.io.Closeable; | ||
|
|
||
| final class CloseableResource implements Closeable { | ||
| @Override | ||
| public void close() {} | ||
| } | ||
|
|
||
| final class AutoCloseableResource implements AutoCloseable { | ||
| @Override | ||
| public void close() {} | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,68 @@ | ||
| // This test covers the Log4j 1.x API in package org.apache.log4j. | ||
| // The RLC-specific stub marks logging methods as @SideEffectFree, so logging after a resource is | ||
| // closed should not wipe out the close fact. | ||
|
|
||
| import java.io.Closeable; | ||
| import org.apache.log4j.Logger; | ||
| import org.checkerframework.checker.calledmethods.qual.EnsuresCalledMethods; | ||
| import org.checkerframework.checker.mustcall.qual.Owning; | ||
|
|
||
| class Log4j1DebugObject implements Closeable { | ||
| private final Logger logger = Logger.getLogger("Log4j1DebugObject"); | ||
| private @Owning CloseableResource resource = new CloseableResource(); | ||
|
|
||
| @Override | ||
| @EnsuresCalledMethods(value = "this.resource", methods = "close") | ||
| public void close() { | ||
| resource.close(); | ||
| logger.debug("after close"); | ||
| } | ||
| } | ||
|
|
||
| class Log4j1DebugWithThrowable implements Closeable { | ||
| private final Logger logger = Logger.getLogger("Log4j1DebugWithThrowable"); | ||
| private @Owning CloseableResource resource = new CloseableResource(); | ||
|
|
||
| @Override | ||
| @EnsuresCalledMethods(value = "this.resource", methods = "close") | ||
| public void close() { | ||
| resource.close(); | ||
| logger.debug("after close", new RuntimeException()); | ||
| } | ||
| } | ||
|
|
||
| class Log4j1InfoObject implements Closeable { | ||
| private final Logger logger = Logger.getLogger("Log4j1InfoObject"); | ||
| private @Owning CloseableResource resource = new CloseableResource(); | ||
|
|
||
| @Override | ||
| @EnsuresCalledMethods(value = "this.resource", methods = "close") | ||
| public void close() { | ||
| resource.close(); | ||
| logger.info("after close"); | ||
| } | ||
| } | ||
|
|
||
| class Log4j1WarnObject implements Closeable { | ||
| private final Logger logger = Logger.getLogger("Log4j1WarnObject"); | ||
| private @Owning CloseableResource resource = new CloseableResource(); | ||
|
|
||
| @Override | ||
| @EnsuresCalledMethods(value = "this.resource", methods = "close") | ||
| public void close() { | ||
| resource.close(); | ||
| logger.warn("after close"); | ||
| } | ||
| } | ||
|
|
||
| class Log4j1ErrorObject implements Closeable { | ||
| private final Logger logger = Logger.getLogger("Log4j1ErrorObject"); | ||
| private @Owning CloseableResource resource = new CloseableResource(); | ||
|
|
||
| @Override | ||
| @EnsuresCalledMethods(value = "this.resource", methods = "close") | ||
| public void close() { | ||
| resource.close(); | ||
| logger.error("after close"); | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change | ||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -0,0 +1,81 @@ | ||||||||||||||||
| // This test covers the Log4j 2.x API in package org.apache.logging.log4j. | ||||||||||||||||
| // real library API. The RLC-specific stub marks logging methods as @SideEffectFree, so logging | ||||||||||||||||
| // after a resource is closed should not wipe out the close fact. | ||||||||||||||||
|
Comment on lines
+1
to
+3
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Update stale/incorrect header comment. Line 2 states "The RLC-specific stub marks logging methods as 📝 Suggested rewrite-// This test covers the Log4j 2.x API in package org.apache.logging.log4j.
-// real library API. The RLC-specific stub marks logging methods as `@SideEffectFree`, so logging
-// after a resource is closed should not wipe out the close fact.
+// This test covers the Log4j 2.x API in package org.apache.logging.log4j.
+// Stubs in framework/src/main/java/org/checkerframework/framework/stub/jdk.astub mark the
+// logging methods as `@SideEffectFree`, so logging after a resource is closed should not wipe
+// out the close fact.📝 Committable suggestion
Suggested change
🤖 Prompt for AI Agents |
||||||||||||||||
|
|
||||||||||||||||
| import java.io.Closeable; | ||||||||||||||||
| import org.apache.logging.log4j.LogManager; | ||||||||||||||||
| import org.apache.logging.log4j.Logger; | ||||||||||||||||
| import org.checkerframework.checker.calledmethods.qual.EnsuresCalledMethods; | ||||||||||||||||
| import org.checkerframework.checker.mustcall.qual.Owning; | ||||||||||||||||
|
|
||||||||||||||||
| class Log4j2DebugObject implements Closeable { | ||||||||||||||||
| private static final Logger logger = LogManager.getLogger(); | ||||||||||||||||
| private @Owning CloseableResource resource = new CloseableResource(); | ||||||||||||||||
|
|
||||||||||||||||
| @Override | ||||||||||||||||
| @EnsuresCalledMethods(value = "this.resource", methods = "close") | ||||||||||||||||
| public void close() { | ||||||||||||||||
| resource.close(); | ||||||||||||||||
| logger.debug("after close"); | ||||||||||||||||
| } | ||||||||||||||||
| } | ||||||||||||||||
|
|
||||||||||||||||
| class Log4j2DebugVarargs implements Closeable { | ||||||||||||||||
| private static final Logger logger = LogManager.getLogger(); | ||||||||||||||||
| private @Owning CloseableResource resource = new CloseableResource(); | ||||||||||||||||
|
|
||||||||||||||||
| @Override | ||||||||||||||||
| @EnsuresCalledMethods(value = "this.resource", methods = "close") | ||||||||||||||||
| public void close() { | ||||||||||||||||
| resource.close(); | ||||||||||||||||
| logger.debug("closed resource {}", "name"); | ||||||||||||||||
| } | ||||||||||||||||
| } | ||||||||||||||||
|
|
||||||||||||||||
| class Log4j2InfoObject implements Closeable { | ||||||||||||||||
| private static final Logger logger = LogManager.getLogger(); | ||||||||||||||||
| private @Owning CloseableResource resource = new CloseableResource(); | ||||||||||||||||
|
|
||||||||||||||||
| @Override | ||||||||||||||||
| @EnsuresCalledMethods(value = "this.resource", methods = "close") | ||||||||||||||||
| public void close() { | ||||||||||||||||
| resource.close(); | ||||||||||||||||
| logger.info("after close"); | ||||||||||||||||
| } | ||||||||||||||||
| } | ||||||||||||||||
|
|
||||||||||||||||
| class Log4j2WarnObject implements Closeable { | ||||||||||||||||
| private static final Logger logger = LogManager.getLogger(); | ||||||||||||||||
| private @Owning CloseableResource resource = new CloseableResource(); | ||||||||||||||||
|
|
||||||||||||||||
| @Override | ||||||||||||||||
| @EnsuresCalledMethods(value = "this.resource", methods = "close") | ||||||||||||||||
| public void close() { | ||||||||||||||||
| resource.close(); | ||||||||||||||||
| logger.warn("after close"); | ||||||||||||||||
| } | ||||||||||||||||
| } | ||||||||||||||||
|
|
||||||||||||||||
| class Log4j2ErrorObject implements Closeable { | ||||||||||||||||
| private static final Logger logger = LogManager.getLogger(); | ||||||||||||||||
| private @Owning CloseableResource resource = new CloseableResource(); | ||||||||||||||||
|
|
||||||||||||||||
| @Override | ||||||||||||||||
| @EnsuresCalledMethods(value = "this.resource", methods = "close") | ||||||||||||||||
| public void close() { | ||||||||||||||||
| resource.close(); | ||||||||||||||||
| logger.error("after close"); | ||||||||||||||||
| } | ||||||||||||||||
| } | ||||||||||||||||
|
|
||||||||||||||||
| class Log4j2ErrorWithThrowable implements Closeable { | ||||||||||||||||
| private static final Logger logger = LogManager.getLogger(); | ||||||||||||||||
| private @Owning CloseableResource resource = new CloseableResource(); | ||||||||||||||||
|
|
||||||||||||||||
| @Override | ||||||||||||||||
| @EnsuresCalledMethods(value = "this.resource", methods = "close") | ||||||||||||||||
| public void close() { | ||||||||||||||||
| resource.close(); | ||||||||||||||||
| logger.error("after close", new RuntimeException()); | ||||||||||||||||
| } | ||||||||||||||||
| } | ||||||||||||||||
|
iamsanjaymalakar marked this conversation as resolved.
|
||||||||||||||||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,47 @@ | ||
| // RLC-specific stubs mark Throwable.printStackTrace overloads as SideEffectFree so | ||
| // that debugging/logging after a resource is closed does not wipe out the close fact. | ||
| // This file checks the no-arg, PrintStream, and PrintWriter variants. | ||
|
|
||
| import java.io.Closeable; | ||
| import java.io.PrintStream; | ||
| import java.io.PrintWriter; | ||
| import java.io.StringWriter; | ||
| import org.checkerframework.checker.calledmethods.qual.EnsuresCalledMethods; | ||
| import org.checkerframework.checker.mustcall.qual.Owning; | ||
|
|
||
| class ThrowablePrintStackTrace implements Closeable { | ||
| private @Owning CloseableResource resource = new CloseableResource(); | ||
|
|
||
| @Override | ||
| @EnsuresCalledMethods(value = "this.resource", methods = "close") | ||
| public void close() { | ||
| resource.close(); | ||
| new RuntimeException("debug").printStackTrace(); | ||
| } | ||
| } | ||
|
|
||
| class ThrowablePrintStackTracePrintStream implements Closeable { | ||
| private static final PrintStream STREAM = System.err; | ||
|
|
||
| private @Owning CloseableResource resource = new CloseableResource(); | ||
|
|
||
| @Override | ||
| @EnsuresCalledMethods(value = "this.resource", methods = "close") | ||
| public void close() { | ||
| resource.close(); | ||
| new RuntimeException("debug").printStackTrace(STREAM); | ||
| } | ||
| } | ||
|
|
||
| class ThrowablePrintStackTracePrintWriter implements Closeable { | ||
| private static final PrintWriter WRITER = new PrintWriter(new StringWriter()); | ||
|
|
||
| private @Owning CloseableResource resource = new CloseableResource(); | ||
|
|
||
| @Override | ||
| @EnsuresCalledMethods(value = "this.resource", methods = "close") | ||
| public void close() { | ||
| resource.close(); | ||
| new RuntimeException("debug").printStackTrace(WRITER); | ||
| } | ||
| } |
Uh oh!
There was an error while loading. Please reload this page.