message("TESTING: finalize() reentrant...")

## FIXME: 'covr' does not play well with tests
## detaching/unloading packages
if ("covr" %in% loadedNamespaces()) {
  detach <- function(...) NULL
}


library("R.methodsS3")
library("R.oo")

lotsOfParsing <- function(code="y <- 1:3") {
  parse(text=rep(code, times=10000))
}

setConstructorS3("MyClass", function(a=1:10) {
  extend(Object(), "MyClass", a=a)
})

setMethodS3("finalize", "MyClass", function(this, ...) {
  cat("finalize...\n")
  utils::str(sys.calls())
  cat("finalize...done\n")
})

# Parse and eval expression (works)
expr <- lotsOfParsing()
eval(expr)
print(y)
## [1] 1 2 3
stopifnot(identical(y, 1:3))

# Create an object with a finalizer
x <- MyClass()

# Detach R.oo so that the finalizer will try to reload it
detach("package:R.oo")

# Remove 'x' so that it will be finalized below
rm(x)


# This may trigger garbage collection via parse()
# If so, it is important that parse() is not called
# (indirectly via library()) by the finalizer.
# Because otherwise R may crash.
expr2 <- lotsOfParsing(code="y <- 1:4")
## finalize...
## Dotted pair list of 9
##  $ : ...
##  ...
##  $ : language function (env)  { ...
##  $ : language finalize(this)
##  $ : language finalize.MyClass(this)
## Parse called: TRUE
## finalize...done
eval(expr2)
print(y)
## [1] 1 2 3 4
stopifnot(identical(y, 1:4))

print(warnings())

message("TESTING: finalize() reentrant...DONE")
