test/rss-tests.lisp

DOWNLOAD
(defpackage murja.tests.rss 
  (:use :cl :fiveam)
  (:import-from :murja.users.user-db :register-user)
  (:import-from :murja.rss.reader-db :update-feeds)
  (:import-from :easy-routes :defroute)
  (:import-from :halisql :*system-name*)
  (:import-from :lisp-fixup :slurp-utf-8)
  (:import-from :murja.tests :prepare-db-and-server :drakma->string :url :main-suite :prepare-db-and-server))

(in-package :murja.tests.rss)
(in-suite main-suite)

;; let's mock a few rss feeds that return something sensible in their Last-Modified
(defvar rss-sample (slurp-utf-8
		    (asdf:system-relative-pathname *system-name*
						   "resources/test/rss-sample.xml")))
(defvar rss1-hook nil)

(defvar rss1route-called nil)
(defroute test-route ("/api/rssdemo1" :method :get) ()
  (assert (not (equalp rss1route-called nil)))
  (incf rss1route-called)
  (format t "Returning rss from rssdemo1, callcounter is ~d~%" rss1route-called)
  (when rss1-hook
    (log:info "calling test hook #1~%")
    (funcall rss1-hook))
  (setf (hunchentoot:content-type*) "application/rss+xml")
  (setf (hunchentoot:header-out "Last-Modified") "Mon, 06 May 2024 23:23:23 GMT")
  rss-sample)

(defvar rss2route-called nil)
(defvar rss2-hook nil)
(defroute test-route2 ("/api/rssdemo2" :method :get) ()
  (assert (not (equalp rss2route-called nil)))
  (incf rss2route-called)
  (format t "Returning rss from rssdemo2, callcounter is ~d~%" rss2route-called)
  (when rss2-hook
    (log:info "rss2-hook: ~a" rss2-hook)
    (funcall rss2-hook))
  (setf (hunchentoot:content-type*) "application/rss+xml")
  (setf (hunchentoot:header-out "Last-Modified") "Mon, 01 Jan 2024 22:21:20 GMT")
  (log:info "returning from rssdemo2~%")
  rss-sample)

(defvar amount-of-if-modified-sinces nil)
(defvar is-called nil)

;; the actual tests 
(def-test reader-test (:fixture prepare-db-and-server)
  (register-user "testuser" "Testuser" "" "passw0rd")
  (setf rss1route-called 0)
  (setf rss2route-called 0)
  (setf amount-of-if-modified-sinces 0)
  (unwind-protect 
       (let ((feed-urls (mapcar
			 (lisp-fixup:partial #'format nil "~a/api/rssdemo~d" (url))
			 (lisp-fixup:range2 1 3)))
	     (feed-names (mapcar
			  (lisp-fixup:partial #'format nil "rss-~d")
			  (lisp-fixup:range2 1 3)))
	     (owner (caar (postmodern:query "SELECT ID FROM blog.Users"))))
	 (is (not (equalp nil owner)))

	 ;; insert the test feeds (update) shall poll
	 (dotimes (i 2)
	   (postmodern:execute "INSERT INTO blog.feed_subscription (name, url, owner) VALUES ($1, $2, $3)"
			       (nth i feed-names)
			       (nth i feed-urls)
			       owner))

	 ;; ;; these are supposed to be NULL each
	 (let ((last-modifieds (mapcar #'car (postmodern:query "SELECT last_modified FROM blog.feed_subscription"))))
	   (is (equalp 2
		       (length last-modifieds)))

	   
	   (is (every (lisp-fixup:partial #'equalp :null) last-modifieds)))

	 (update-feeds)

	 ;; both feed endpoints are called
	 (is (equalp 1 rss1route-called))
	 (is (equalp 1 rss2route-called))

	 ;; these are now supposed be something sensible
	 (let ((last-modifieds (mapcar #'car (postmodern:query "SELECT last_modified FROM blog.feed_subscription"))))
	   (is (every (complement (lisp-fixup:partial #'equalp :null)) last-modifieds))

	   ;; let's use hooks to see if the last last-modified is sent in the if-modified-since
	   (let ((hook (lambda ()
			       (setf is-called t)
			       (log:info "Set is-called into t; if-modified-since: ~a~%" (hunchentoot:header-in* "if-modified-since"))
			       
			       (when (hunchentoot:header-in* "if-modified-since")
				 (incf amount-of-if-modified-sinces)))))
	     (setf rss1-hook hook)
	     (setf rss2-hook hook)
	     
	     (setf murja.rss.reader-db:*last-updated* nil)
	     (log:info "re-updating feeds")
	     (update-feeds)
	     (is (not (equalp nil is-called)))
	     (is (equalp amount-of-if-modified-sinces 2)))))
    (setf rss1route-called nil)
    (setf rss2route-called nil)

    (setf rss1-hook nil)
    (setf rss2-hook nil)
    (setf amount-of-if-modified-sinces nil)
    (setf is-called nil)))