all messages for Guix-related lists mirrored at yhetil.org
 help / color / mirror / code / Atom feed
* Guix Scripts and Unit Testing
@ 2022-02-12 17:21 Phil
  2022-02-13 20:58 ` Phil
  0 siblings, 1 reply; 3+ messages in thread
From: Phil @ 2022-02-12 17:21 UTC (permalink / raw)
  To: Guix Devel

[-- Attachment #1: Type: text/plain, Size: 2920 bytes --]

Hi Guix,

I have some Guix scripts which take the form of manifests
(--manifest=file), packages (--load=file), or are called using "guix
repl".  Some of these are complex enough to warrant writing unit tests for
using srfi-64.  However, I'm having some difficulty trying to work out how
to run unit tests over procedures that are also used to descirbe manifests
and repl scripts, and was looking for some advice - details below!

Normally in vanilla Guile I'd structure my code to call a main procedure
using the Guile meta-switch, thus the script could also be imported by a
test script using "use-modules" or executed using the meta-switch:
https://www.gnu.org/software/guile/manual/html_node/The-Meta-Switch.html

However there is no way of doing this (that I can figure out) when the
script is being passed to "guix envrionment" or "guix repl" - meaning the
contents of my "main" procedure cannot be bound by a function in the script.

To try to work around this, I separated my scripts into a library module to
be unit tested, and a short runner which will call into the library module
to generate the manifest, however this approach produces unexpected
behaviour - for example if I have a simple *gurobi-manifest.scm* like so:







*(add-to-load-path (dirname (current-filename))) ;; put the script's
location on the module path(use-modules (gurobi-transform-lib)) ;; load the
script library(newline)(packages->manifest (list my-package-with-my-gurobi*

*                          (specification->package "python"))) ;; add
python for convenience*

The procedure we call to generate the package - *my-package-with-my-gurobi*,
is in a file called *gurobi-transform-lib.scm* in the same directory as the
manifest above.

The initial call to the *my-package-with-my-gurobi* succeeds (The stdout
below shows this) but failure quickly follows, with a subsequent call to
the library failing:








*$ guix environment -m gurobi-manifest.scmSetting Gurobi Version: 9.1.2 <-
everything looks OK to start withSetting Test Package: simmguix
environment: error: failed to load
'gurobi-manifest.scm':ice-9/boot-9.scm:3329:6: In procedure
resolve-interface:no code for module (gurobi-transform-lib)*

*$*

If I cut and paste the library and manifest into the same file everything
works as expected.

Thus the best workaround I have at the moment is to have the unit tests run
directly from the manifest script, every time the manifest is used, but
this is only practical for a very small number of unit tests, and even then
it's a bit ugly.

Can anyone suggest a better way of having the unit tests in a separate file
which can import procedures used in repl or manifest scripts in such a way
that they still work or can be used as repl or manifest scripts themselves?

In the above example, I was hoping to have something like:

*guix repl -- gurobi-transform-lib-tests.scm*

Any ideas greatfully received!

Cheers,
Phil.

[-- Attachment #2: Type: text/html, Size: 4312 bytes --]

^ permalink raw reply	[flat|nested] 3+ messages in thread

* Re: Guix Scripts and Unit Testing
  2022-02-12 17:21 Guix Scripts and Unit Testing Phil
@ 2022-02-13 20:58 ` Phil
  2022-02-15 18:08   ` Phil
  0 siblings, 1 reply; 3+ messages in thread
From: Phil @ 2022-02-13 20:58 UTC (permalink / raw)
  To: Guix Devel

[-- Attachment #1: Type: text/plain, Size: 2622 bytes --]

I have a theory about what is causing this - I think it's me not thinking
about deferred evaluation carefully enough.

On Sat, 12 Feb 2022 at 17:21, Phil <phil@beadling.co.uk> wrote:

>
> To try to work around this, I separated my scripts into a library module
> to be unit tested, and a short runner which will call into the library
> module to generate the manifest, however this approach produces unexpected
> behaviour - for example if I have a simple *gurobi-manifest.scm* like so:
>
>
>
>
>
>
>
> *(add-to-load-path (dirname (current-filename))) ;; put the script's
> location on the module path(use-modules (gurobi-transform-lib)) ;; load the
> script library(newline)(packages->manifest (list my-package-with-my-gurobi*
>
> *                          (specification->package "python"))) ;; add
> python for convenience*
>
> The procedure we call to generate the package -
> *my-package-with-my-gurobi*, is in a file called
> *gurobi-transform-lib.scm* in the same directory as the manifest above.
>
>

This is crux of the issue - I think it's an issue with where the code for
my package is evaluated.

If I move just 2 functions back from my library into the manifest itself,
then everything works exactly as I'd expect.











*;; Prompt for Gurobi package if not set in env var(define
my-gurobi-package ((transform) (specification->package "gurobipy")))(define
my-package-with-my-gurobi  (let* ((test-package-string
(get-env-var-or-prompt "GUIX_TEST_PACKAGE"))         (test-package
(specification->package test-package-string)))    (format #t "~%Setting
Test Package: ~a~%" test-package-string)    (package/inherit test-package
                   (propagated-inputs                      `(("gurobipy"
,my-gurobi-package) ;; add my new gurobi
,@(alist-delete "gurobipy" (package-propagated-inputs test-package)))))))
;; remove the original gurobi and splice*

What I think is happening is that the propagated-inputs in my newly created
test-package will have their evaluation delayed until the build occurs in
the daemon.  I presume at this point my local library I've used
add-to-load-path to include in the manifest will no longer be accessible
and hence the eval failure being returned.

IIRC there is a key you can add to package definitons to request module
loading on the daemon side as part of the build process - if something like
was to exist then it might be possible to move these 2 functions back to
the library rather than having them in the manifest, but as it stands it
seems the daemon has visibilty of the manifest script itself, but not
load-path and modules as set in the manifest script.

[-- Attachment #2: Type: text/html, Size: 3682 bytes --]

^ permalink raw reply	[flat|nested] 3+ messages in thread

* Re: Guix Scripts and Unit Testing
  2022-02-13 20:58 ` Phil
@ 2022-02-15 18:08   ` Phil
  0 siblings, 0 replies; 3+ messages in thread
From: Phil @ 2022-02-15 18:08 UTC (permalink / raw)
  To: Guix Devel

[-- Attachment #1: Type: text/plain, Size: 2102 bytes --]

This is largely resolved now - turns out my code sucked rather than needing
to do something clever with Guix module importing, which is what I
suspected ;-)

The only compromise I'm making now is that any complicated manifest for
example, I am having to split into a trivial manifest script calling into a
library that I can then unit test - so it's not quite as good as having a
meta switch for manifests or repl scripts, but it's good enough.

On Sun, 13 Feb 2022 at 20:58, Phil <phil@beadling.co.uk> wrote:

> I have a theory about what is causing this - I think it's me not thinking
> about deferred evaluation carefully enough.
>

This is true, but my second post was still missing the point!


>
> What I think is happening is that the propagated-inputs in my newly
> created test-package will have their evaluation delayed until the build
> occurs in the daemon.  I presume at this point my local library I've used
> add-to-load-path to include in the manifest will no longer be accessible
> and hence the eval failure being returned.
>
>
>
The problem was actually much easier to solve than I had originally
over-thought - simply by making my-package- with-my-gurobi a procedure
which returns the package rather than having it defined as a variable that
contains a package all the problems go away apart from a handful of imports
required in the library script.  The my-gurobi-package can also be nested
inside the let statement, and the whole procedure added to the library.

(define (my-package-with-my-gurobi)
  (let* ((test-package-string (get-env-var-or-prompt "GUIX_TEST_PACKAGE"))
         (test-package (specification->package test-package-string))
         (my-gurobi-package ((transform) (specification->package
"gurobipy"))))
    (format #t "~%Setting Test Package: ~a~%" test-package-string)
    (package/inherit test-package
                     (propagated-inputs
                      `(("gurobipy" ,my-gurobi-package) ;; add my new gurobi
                        ,@(alist-delete "gurobipy"
(package-propagated-inputs test-package))))))) ;; remove the original
gurobi and splice

[-- Attachment #2: Type: text/html, Size: 3107 bytes --]

^ permalink raw reply	[flat|nested] 3+ messages in thread

end of thread, other threads:[~2022-02-15 18:09 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2022-02-12 17:21 Guix Scripts and Unit Testing Phil
2022-02-13 20:58 ` Phil
2022-02-15 18:08   ` Phil

Code repositories for project(s) associated with this external index

	https://git.savannah.gnu.org/cgit/guix.git

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.