vnstat.scm 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157
  1. ;;; GNU Guix --- Functional package management for GNU
  2. ;;; Copyright © 2023 Bruno Victal <mirai@makinata.eu>.
  3. ;;;
  4. ;;; This file is part of GNU Guix.
  5. ;;;
  6. ;;; GNU Guix is free software; you can redistribute it and/or modify it
  7. ;;; under the terms of the GNU General Public License as published by
  8. ;;; the Free Software Foundation; either version 3 of the License, or (at
  9. ;;; your option) any later version.
  10. ;;;
  11. ;;; GNU Guix is distributed in the hope that it will be useful, but
  12. ;;; WITHOUT ANY WARRANTY; without even the implied warranty of
  13. ;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14. ;;; GNU General Public License for more details.
  15. ;;;
  16. ;;; You should have received a copy of the GNU General Public License
  17. ;;; along with GNU Guix. If not, see <http://www.gnu.org/licenses/>.
  18. (define-module (gnu tests vnstat)
  19. #:use-module (gnu tests)
  20. #:use-module ((gnu packages networking) #:select (socat vnstat))
  21. #:use-module (gnu services)
  22. #:use-module (gnu services networking)
  23. #:use-module (gnu services monitoring)
  24. #:use-module (gnu system)
  25. #:use-module (gnu system vm)
  26. #:use-module (guix gexp)
  27. #:use-module (ice-9 format)
  28. #:export (%test-vnstat))
  29. (define (run-vnstat-test)
  30. "Run tests in a vm which has vnstat running."
  31. (define vnstat-config
  32. (vnstat-configuration
  33. (max-bandwidth 0)
  34. (time-sync-wait 0)
  35. (bandwidth-detection-interval 0)))
  36. (define inetd-service-entry-config
  37. (inetd-entry
  38. (name "discard")
  39. (socket-type 'stream)
  40. (protocol "tcp")
  41. (wait? #t)
  42. (user "nobody")))
  43. (define os
  44. (marionette-operating-system
  45. (simple-operating-system
  46. (service dhcp-client-service-type)
  47. (service vnstat-service-type
  48. vnstat-config)
  49. (service inetd-service-type
  50. (inetd-configuration
  51. (entries
  52. (list inetd-service-entry-config)))))
  53. #:imported-modules '((gnu services herd))))
  54. (define forwarded-port 9999)
  55. (define vm
  56. ;; The 'discard' port is 9. Avoid using 'getservbyname' as that might
  57. ;; fail depending on what /etc/services has (if it's available).
  58. (let ((guest-port 9))
  59. (virtual-machine
  60. (operating-system os)
  61. (port-forwardings `((,forwarded-port . ,guest-port))))))
  62. ;; The test duration is inconsistent, at times a test may complete under
  63. ;; 2 minutes and at times it may take up to 5 minutes.
  64. (define test-timeout (* 60 5))
  65. (define test
  66. (with-imported-modules '((gnu build marionette))
  67. #~(begin
  68. (use-modules (gnu build marionette)
  69. (srfi srfi-64))
  70. (let ((marionette (make-marionette (list #$vm)))
  71. (pid-file #$(vnstat-configuration-pid-file vnstat-config)))
  72. (test-runner-current (system-test-runner #$output))
  73. (test-begin "vnstat")
  74. (test-assert "service is running"
  75. (marionette-eval
  76. '(begin
  77. (use-modules (gnu services herd))
  78. (start-service 'vnstatd))
  79. marionette))
  80. (test-assert "vnstatd ready"
  81. (wait-for-file pid-file marionette))
  82. ;; Pump garbage into the 'discard' inetd service within the vm.
  83. (let* ((socat #$(file-append socat "/bin/socat"))
  84. (dest-addr #$(format #f "TCP4:localhost:~d"
  85. forwarded-port))
  86. (args `("socat" "-u" "/dev/zero" ,dest-addr))
  87. ;; XXX: Guile bug (22/03/2023, Guile 3.0.9)
  88. ;; Fixed in main: <https://issues.guix.gnu.org/61073>
  89. ;; FIXME: re-add #:output (%make-void-port "w") below on
  90. ;; next Guile release.
  91. (garbage-pump-pid
  92. (spawn socat args)))
  93. (test-group-with-cleanup "Logging"
  94. ;; To aid debugging, this test returns #t on success
  95. ;; and either #f or 'timed-out otherwise.
  96. (test-eq "vnstatd is logging"
  97. #t
  98. (marionette-eval
  99. '(begin
  100. (use-modules (ice-9 popen)
  101. (ice-9 match)
  102. (sxml simple)
  103. (sxml xpath))
  104. (define selector
  105. (let ((xpath '(vnstat interface traffic total)))
  106. (compose (node-pos 1) (sxpath xpath))))
  107. (let loop ((i 0))
  108. (let* ((vnstat #$(file-append vnstat "/bin/vnstat"))
  109. (query-cmd (format #f "~a --xml" vnstat))
  110. (proc (compose selector xml->sxml))
  111. (result
  112. (call-with-port
  113. (open-input-pipe query-cmd) proc)))
  114. (match result
  115. ;; Counter still warming up.
  116. ((('total ('rx "0") ('tx "0")))
  117. (sleep 1)
  118. (if (< i #$test-timeout)
  119. (loop (+ i 1))
  120. 'timed-out))
  121. ;; Count of bytes on iface was non-zero.
  122. ((('total ('rx rx) ('tx tx)))
  123. #t)
  124. ;; Unknown data encountered, perhaps the
  125. ;; data format changed?
  126. (_ #f)))))
  127. marionette))
  128. ;; Cleanup: shutdown garbage pump.
  129. (kill garbage-pump-pid SIGTERM)))
  130. (test-end)))))
  131. (gexp->derivation "vnstat-test" test))
  132. (define %test-vnstat
  133. (system-test
  134. (name "vnstat")
  135. (description "Basic tests for vnstat service.")
  136. (value (run-vnstat-test))))