aboutsummaryrefslogtreecommitdiff
;;; GNU Guix --- Functional package management for GNU
;;; Copyright © 2021, 2022, 2023 Maxim Cournoyer <maxim.cournoyer@gmail.com>.
;;;
;;; This file is part of GNU Guix.
;;;
;;; GNU Guix is free software; you can redistribute it and/or modify it
;;; under the terms of the GNU General Public License as published by
;;; the Free Software Foundation; either version 3 of the License, or (at
;;; your option) any later version.
;;;
;;; GNU Guix is distributed in the hope that it will be useful, but
;;; WITHOUT ANY WARRANTY; without even the implied warranty of
;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
;;; GNU General Public License for more details.
;;;
;;; You should have received a copy of the GNU General Public License
;;; along with GNU Guix.  If not, see <http://www.gnu.org/licenses/>.

(define-module (gnu tests telephony)
  #:use-module (gnu)
  #:use-module (gnu packages)
  #:use-module (gnu packages guile)
  #:use-module (gnu packages guile-xyz)
  #:use-module (gnu tests)
  #:use-module (gnu system vm)
  #:use-module (gnu services)
  #:use-module (gnu services dbus)
  #:use-module (gnu services networking)
  #:use-module (gnu services ssh)
  #:use-module (gnu services telephony)
  #:use-module (guix gexp)
  #:use-module (guix modules)
  #:export (%test-jami
            %test-jami-provisioning
            %test-jami-provisioning-partial))

;;;
;;; Jami daemon.
;;;

(define %jami-account-content-sexp
  (call-with-input-file
      (search-path %load-path "gnu/tests/data/jami-dummy-account.dat")
    read))

(define %dummy-jami-account-archive
  ;; A Jami account archive is a gzipped JSON file.
  (computed-file
   "dummy-jami-account.gz"
   (with-extensions (list guile-json-4 guile-zlib)
     #~(begin
         (use-modules (json) (zlib))
         (let ((port (open-output-file #$output)))
           (call-with-gzip-output-port port
             (lambda (port)
               (scm->json '#$%jami-account-content-sexp port))))))))

(define %allowed-contacts '("1dbcb0f5f37324228235564b79f2b9737e9a008f"
                            "2dbcb0f5f37324228235564b79f2b9737e9a008f"))

(define %moderators '("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
                      "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb"))

(define %dummy-jami-account (jami-account
                             (archive %dummy-jami-account-archive)
                             (allowed-contacts %allowed-contacts)
                             (moderators %moderators)
                             (rendezvous-point? #t)
                             (peer-discovery? #f)
                             (bootstrap-hostnames '("bootstrap.me"
                                                    "fallback.another.host"))
                             (name-server-uri "https://my.name.server")))

;;; Like %dummy-jami-account, but with allowed-contacts and moderators left
;;; unset (thus taking the value *unspecified*).
(define %dummy-jami-account-partial
  (jami-account
   (archive %dummy-jami-account-archive)
   (rendezvous-point? #t)
   (peer-discovery? #f)
   (bootstrap-hostnames '("bootstrap.me"
                          "fallback.another.host"))
   (name-server-uri "https://my.name.server")))

(define* (make-jami-os #:key provisioning? partial?)
  (operating-system
    (host-name "jami")
    (timezone "America/Montreal")
    (locale "en_US.UTF-8")

    (bootloader (bootloader-configuration
                 (bootloader grub-bootloader)
                 (targets '("/dev/sdX"))))
    (file-systems (cons (file-system
                          (device (file-system-label "my-root"))
                          (mount-point "/")
                          (type "ext4"))
                        %base-file-systems))
    (firmware '())

    (services (cons* (service jami-service-type
                              (if provisioning?
                                  (jami-configuration
                                   (debug? #t)
                                   (accounts
                                    (list (if partial?
                                              %dummy-jami-account-partial
                                              %dummy-jami-account))))
                                  (jami-configuration
                                   (debug? #t))))
                     (service dbus-root-service-type)
                     ;; The following services/packages are added for
                     ;; debugging purposes.
                     (service dhcp-client-service-type)
                     (service openssh-service-type
                              (openssh-configuration
                               (permit-root-login #t)
                               (allow-empty-passwords? #t)))
                     %base-services))
    (packages (cons* (specification->package "recutils")
                     (specification->package "strace")
                     %base-packages))))

(define %jami-os
  (make-jami-os))

(define %jami-os-provisioning
  (make-jami-os #:provisioning? #t))

(define %jami-os-provisioning-partial
  (make-jami-os #:provisioning? #t #:partial? #t))

(define* (run-jami-test #:key provisioning? partial?)
  "Run tests in %JAMI-OS.  When PROVISIONING? is true, test the accounts
provisioning feature of the service.  When PARTIAL? is #t, some fields of the
jami account used as part of the jami configuration are left *unspecified*."
  (define os (marionette-operating-system
              (if provisioning?
                  (if partial?
                      %jami-os-provisioning-partial
                      %jami-os-provisioning)
                  %jami-os)
              #:imported-modules '((gnu services herd)
                                   (guix combinators)
                                   (gnu build jami-service)
                                   (gnu build dbus-service))))
  (define vm (virtual-machine
              (operating-system os)
              (memory-size 512)))

  (define username (assoc-ref %jami-account-content-sexp
                              "Account.username"))

  (define test
    (with-imported-modules (source-module-closure
                            '((gnu build marionette)))
      #~(begin
          (use-modules (srfi srfi-64)
                       (gnu build marionette))

          (define marionette
            (make-marionette (list #$vm)))

          (test-runner-current (system-test-runner #$output))
          (test-begin "jami")

          (test-assert "d-bus tooling loaded"
            ;; Add Guile-AC-D-Bus and related libraries to the marionette's
            ;; search path.
            (marionette-eval
             '(let ((libraries '(#$guile-ac-d-bus
                                 #$guile-packrat))) ;used by ac-d-bus
                (setenv "DBUS_SESSION_BUS_ADDRESS" "unix:path=/var/run/jami/bus")
                (set! %load-path
                      (append %load-path
                              (map (lambda (directory)
                                     (string-append directory
                                                    "/share/guile/site/"
                                                    (effective-version)))
                                   libraries)))
                (set! %load-compiled-path
                      (append %load-compiled-path
                              (map (lambda (directory)
                                     (string-append directory
                                                    "/lib/guile/3.0/site-ccache"))
                                   libraries)))
                %load-path)
             marionette))

          (test-assert "dbus session is up"
            (and (marionette-eval
                  '(begin
                     (use-modules (gnu services herd))
                     (wait-for-service 'jami-dbus-session #:timeout 40))
                  marionette)
                 (wait-for-unix-socket "/var/run/jami/bus"
                                       marionette)))

          (test-assert "service is running"
            (marionette-eval
             '(begin
                (use-modules (gnu build jami-service)
                             (gnu services herd))

                (wait-for-service 'jami #:timeout 40)
                (jami-service-available?))
             marionette))

          (test-assert "service can be stopped"
            (marionette-eval
             '(begin
                (use-modules (gnu build dbus-service)
                             (gnu build jami-service)
                             (gnu services herd)
                             (rnrs base))
                (assert (jami-service-available?))

                (stop-service 'jami)

                (with-retries 20 1 (not (jami-service-available?))))
             marionette))

          (test-assert "service can be restarted"
            (marionette-eval
             '(begin
                (use-modules (gnu build dbus-service)
                             (gnu build jami-service)
                             (gnu services herd)
                             (rnrs base)                               )
                ;; Start the service.
                (start-service 'jami)
                (with-retries 40 1 (jami-service-available?))
                ;; Restart the service.
                (restart-service 'jami)
                (with-retries 40 1 (jami-service-available?)))
             marionette))

          (unless #$provisioning? (test-skip 1))
          (test-assert "jami accounts provisioning, account present"
            (marionette-eval
             '(begin
                (use-modules (gnu build dbus-service)
                             (gnu services herd)
                             (rnrs base))
                ;; Accounts take some time to appear after being added.
                (with-retries 40 1
                              (with-shepherd-action 'jami ('list-accounts) results
                                (let ((account (assoc-ref (car results) #$username)))
                                  (assert (string=? #$username
                                                    (assoc-ref account
                                                               "Account.username")))))))
             marionette))

          (unless #$(and provisioning? (not partial?)) (test-skip 1))
          (test-assert "jami accounts provisioning, allowed-contacts"
            (marionette-eval
             '(begin
                (use-modules (gnu services herd)
                             (rnrs base)
                             (srfi srfi-1))

                ;; Public mode is disabled.
                (with-shepherd-action 'jami ('list-account-details)
                                      results
                  (let ((account (assoc-ref (car results) #$username)))
                    (assert (string=? "false"
                                      (assoc-ref account
                                                 "DHT.PublicInCalls")))))

                ;; Allowed contacts match those declared in the configuration.
                (with-shepherd-action 'jami ('list-contacts) results
                  (let ((contacts (assoc-ref (car results) #$username)))
                    (assert (lset= string-ci=? contacts '#$%allowed-contacts)))))
             marionette))

          (unless #$(and provisioning? (not partial?)) (test-skip 1))
          (test-assert "jami accounts provisioning, moderators"
            (marionette-eval
             '(begin
                (use-modules (gnu services herd)
                             (rnrs base)
                             (srfi srfi-1))

                ;; Moderators match those declared in the configuration.
                (with-shepherd-action 'jami ('list-moderators) results
                  (let ((moderators (assoc-ref (car results) #$username)))
                    (assert (lset= string-ci=? moderators '#$%moderators))))

                ;; Moderators can be added via the Shepherd action.
                (with-shepherd-action 'jami
                    ('add-moderator "cccccccccccccccccccccccccccccccccccccccc"
                                    #$username) results
                  (let ((moderators (car results)))
                    (assert (lset= string-ci=? moderators
                                   (cons "cccccccccccccccccccccccccccccccccccccccc"
                                         '#$%moderators))))))
             marionette))

          (unless #$provisioning? (test-skip 1))
          (test-assert "jami service actions, ban/unban contacts"
            (marionette-eval
             '(begin
                (use-modules (gnu services herd)
                             (ice-9 match)
                             (rnrs base)
                             (srfi srfi-1))

                ;; Globally ban a contact.
                (with-shepherd-action 'jami
                    ('ban-contact "1dbcb0f5f37324228235564b79f2b9737e9a008f") _
                  (with-shepherd-action 'jami ('list-banned-contacts) results
                    (every (match-lambda
                             ((username . banned-contacts)
                              (member "1dbcb0f5f37324228235564b79f2b9737e9a008f"
                                      banned-contacts)))
                           (car results))))

                ;; Ban a contact for a single account.
                (with-shepherd-action 'jami
                    ('ban-contact "dddddddddddddddddddddddddddddddddddddddd"
                                  #$username) _
                  (with-shepherd-action 'jami ('list-banned-contacts) results
                    (every (match-lambda
                             ((username . banned-contacts)
                              (let ((found? (member "dddddddddddddddddddddddddddddddddddddddd"
                                                    banned-contacts)))
                                (if (string=? #$username username)
                                    found?
                                    (not found?)))))
                           (car results)))))
             marionette))

          (unless #$provisioning? (test-skip 1))
          (test-assert "jami service actions, enable/disable accounts"
            (marionette-eval
             '(begin
                (use-modules (gnu services herd)
                             (rnrs base))

                (with-shepherd-action 'jami
                    ('disable-account #$username) _
                  (with-shepherd-action 'jami ('list-accounts) results
                    (let ((account (assoc-ref (car results) #$username)))
                      (assert (string= "false"
                                       (assoc-ref account "Account.enable"))))))

                (with-shepherd-action 'jami
                    ('enable-account #$username) _
                  (with-shepherd-action 'jami ('list-accounts) results
                    (let ((account (assoc-ref (car results) #$username)))
                      (assert (string= "true"
                                       (assoc-ref account "Account.enable")))))))
             marionette))

          (unless #$provisioning? (test-skip 1))
          (test-assert "jami account parameters"
            (marionette-eval
             '(begin
                (use-modules (gnu services herd)
                             (rnrs base)
                             (srfi srfi-1))

                (with-shepherd-action 'jami ('list-account-details) results
                  (let ((account-details (assoc-ref (car results)
                                                    #$username)))
                    (assert (lset<=
                             equal?
                             '(("Account.hostname" .
                                "bootstrap.me;fallback.another.host")
                               ("Account.peerDiscovery" . "false")
                               ("Account.rendezVous" . "true")
                               ("RingNS.uri" . "https://my.name.server"))
                             account-details)))))
             marionette))

          (test-end))))

  (gexp->derivation (if provisioning?
                        (if partial?
                            "jami-provisioning-partial-test"
                            "jami-provisioning-test")
                        "jami-test")
                    test))

(define %test-jami
  (system-test
   (name "jami")
   (description "Basic tests for the jami service.")
   (value (run-jami-test))))

(define %test-jami-provisioning
  (system-test
   (name "jami-provisioning")
   (description "Provisioning test for the jami service.")
   (value (run-jami-test #:provisioning? #t))))

;;; This test verifies that <jami-account> values can be left unspecified
;;; without causing any issue (see: https://issues.guix.gnu.org/56799).
(define %test-jami-provisioning-partial
  (system-test
   (name "jami-provisioning-partial")
   (description "Provisioning test for the jami service, when some of the
'maybe' fields aren't provided (such that their value end up being
*unspecified*.")
   (value (run-jami-test #:provisioning? #t #:partial? #t))))
14:08:07 +0200'>2022-08-01gnu: xdot: Build with librsvg-for-system....* gnu/packages/graphviz.scm (xdot)[inputs]: Replace librsvg with librsvg-for-system. Signed-off-by: Ludovic Courtès <ludo@gnu.org> Denis 'GNUtoo' Carikli 2022-08-01gnu: Add cardpeek....* gnu/packages/security-token.scm (cardpeek): New variable. Signed-off-by: Ludovic Courtès <ludo@gnu.org> Denis 'GNUtoo' Carikli 2022-08-01gnu: python-sep: Update to 1.2.1...* gnu/packages/astronomy.scm: (python-sep): Update to 1.2.1. Inherit from libsep Signed-off-by: Ludovic Courtès <ludo@gnu.org> Sharlatan Hellseher 2022-08-01gnu: Add libsep...* gnu/packages/astronomy.scm: (libsep): New variable. Signed-off-by: Ludovic Courtès <ludo@gnu.org> Sharlatan Hellseher 2022-08-01gnu: gnutls: Add 3.7.7....* gnu/packages/tls.scm (gnutls-latest): New variable. Ludovic Courtès 2022-08-01gnu: python-bbknn: Set NUMBA_CACHE_DIR....* gnu/packages/bioinformatics.scm (python-bbknn)[arguments]: Add phase 'set-numba-cache-dir. Ricardo Wurmus 2022-08-01gnu: python-umap-learn: Disable unreliable test....* gnu/packages/machine-learning.scm (python-umap-learn)[arguments]: Disable test_densmap_trustworthiness_on_iris_supervised. Ricardo Wurmus 2022-08-01gnu: python-umap-learn: Set NUMBA_CACHE_DIR....* gnu/packages/machine-learning.scm (python-umap-learn)[arguments]: Add phase to set NUMBA_CACHE_DIR. Ricardo Wurmus 2022-07-31gnu: jami: Apply upstream patch that fixes a usability issue....* gnu/packages/patches/jami-fix-esc-bug.patch: New patch. * gnu/local.mk (dist_patch_DATA): Register it. * gnu/packages/jami.scm (%jami-sources): Apply it. Maxim Cournoyer 2022-07-31gnu: jami: Update to 20220726.1515.da8d1da....* gnu/packages/jami.scm (jami): Update to 20220726.1515.da8d1da. [configure-flags]: New argument. [phases]{fix-version-string}: Adjust file name. {use-desktop-opengl}: Delete obsolete phase. {patch-source}: New phase. [native-inputs]: Add googletest and vulkan-headers. Replace qttools-5 with qttools. [inputs]: Add libxkbcommon, qt5compat, qtnetworkauth, qtpositioning and vulkan-loader. Remove qtwebengine-5, qtwebchannel-5, qtgraphicaleffects, qtquickcontrols-5 and qtquickcontrols2-5. Update qtsvg-5, qtmultimedia-5 and qtdeclarative-5 to their Qt 6 equivalent. Maxim Cournoyer 2022-07-31gnu: Deprecate jami-gnome for jami....* gnu/packages/jami.scm (jami-gnome): Delete package, deprecating it for jami. Maxim Cournoyer 2022-07-31gnu: Remove jami-libclient....* gnu/packages/jami.scm (jami-libclient): Delete variable. (libringclient): Likewise. (jami-gnome)[inputs]: Remove jami-libclient. (jami)[inputs]: Likewise. Maxim Cournoyer 2022-07-31gnu: libjami: Enable test agent....* gnu/packages/jami.scm (libjami)[configure-flags]: Add '--enable-agent' and remove FIXME. [tests?]: Update comment. Maxim Cournoyer