Fnifni
Fnifni

Reputation: 333

How to test a compiled function?

I have a function do-something, and a function my-function of the form :

(defun my-function ((object object))
  (if (do-something)
    5
    6))

do-something and my-function are in my-package package.

In my-package/tests package, I want to do the following :

(deftest "Test my-function"
  (flet ((my-package::do-something ()
           t))
    (assert-is (my-package::my-function) 5))

  (flet ((my-package::do-something ()
           nil))
    (assert-is (my-package::my-function) 6)))

The goal is to test if my-function behaves correctly, and I would like to keep it as a function (not a macro), and without injecting functions into via the args. In C I could mess with the linker.

Each time I want to run all the updated code and tests, I do the following in the REPL :

(ql:quickload :my-system)
(asdf:test-sytem :my-system/tests)

But it seems it compiles my-function, so even if I do an flet on the do-something function in the test file, the behaviour does not change.

I would like to programmatically test my-function, is there a way to do that ?

Upvotes: 1

Views: 105

Answers (1)

Svante
Svante

Reputation: 51501

Functions defined by flet (or labels) have lexical scope, i. e., they exist only in the flet body. It does not affect the dynamic environment.

There is no explicit support for dynamically rebinding functions, but you can use something like this:

(defmacro with-rebound-fun ((name args &body fun-body) &body body)
  (let ((saved (gensym)))
    `(let ((,saved (symbol-function ',name)))
       (setf (symbol-function ',name) (lambda ,args ,@fun-body))
       (unwind-protect (progn ,@body)
         (setf (symbol-function ',name) ,saved)))))

This is a bit hackish though, and it could break some assumptions an implementation may make about redefining functions. In particular, the symbol might carry additional meta information about the function, which does not get changed. It also will not work where the original function is inlined.

Upvotes: 2

Related Questions