(require :unittest "lib/llib/unittest.l")

(init-unit-test)

(deftest test-hashtable-delete ()
  (let ((ht (make-hash-table :size 10)))
    (dotimes (i (send ht :size))
      (send ht :enter i t)
      (send ht :delete i))
    (assert (find (lisp::hash-table-empty ht) (hash-table-key ht))
            "No empty members left in hash table")))

(deftest test-hashtable-count ()
  (flet ((check-count (ht)
           (assert (= (hash-table-count ht)
                      (- (hash-table-size ht)
                         (count (lisp::hash-table-empty ht) (hash-table-key ht))
                         (count (lisp::hash-table-deleted ht) (hash-table-key ht))))
                   "Hash-table count value does not match!")
           (when (find 'lisp::fill-count (send hash-table :slots))
             (assert (= (ht . lisp::fill-count)
                        (- (hash-table-size ht)
                           (count (lisp::hash-table-empty ht) (hash-table-key ht))))
                     "Hash-table count value does not match!"))))
    (let ((ht (make-hash-table :size 10 :rehash-size 2.0)))
      (dotimes (i 6) (send ht :enter i t))
      (check-count ht)
      (dotimes (i 6) (send ht :delete i))
      (check-count ht)
      (send ht :extend)
      (check-count ht))))

(deftest test-package-unintern ()
  (let ((pkg (make-package (symbol-pname (gensym "TEST-PACKAGE")))))
    (dotimes (i (length (package-intsymvector pkg)))
      (unintern
       (intern (format nil "A~c" (+ #\A i)) pkg)
       pkg))
    (assert (find 0 (package-intsymvector pkg))
            "No empty members left in package")))

(deftest test-package-unintern-export ()
  (let ((pkg (make-package (symbol-pname (gensym "TEST-PACKAGE")))))
    (dotimes (i (length (package-intsymvector pkg)))
      (let ((sym (intern (format nil "A~c" (+ #\A i)) pkg)))
        (export sym pkg)
        (unintern sym pkg)))
    (assert (find 0 (package-intsymvector pkg))
            "No empty internal members left in package")
    (assert (find 0 (package-symvector pkg))
            "No empty external members left in package")))

;; (deftest test-package-enter-unintern ()
;;   (let ((pkg (make-package "TEST-PACKAGE")))
;;     (dotimes (i (length (package-intsymvector pkg)))
;;       (let ((sym (intern (format nil "~c" (+ #\A i)) *user-package*)))
;;         (send pkg :unintern (send pkg :enter sym))))
;;     (assert (find 0 (package-intsymvector pkg))
;;             "No empty members left in package")))

(deftest test-package-intsymcount ()
  (flet ((check-count (pkg)
           (assert (= (package-intsymcount pkg)
                      (- (length (package-intsymvector pkg))
                         (count 0 (package-intsymvector pkg))))
                   "Package intsymcount value does not match!")))
    (let* ((pkg (make-package (symbol-pname (gensym "TEST-PACKAGE"))))
           (half-len (/ (length (package-intsymvector pkg)) 2)))
    (dotimes (i half-len)
      (intern (format nil "A~c" (+ #\A i)) pkg))
    (check-count pkg)
    (dotimes (i half-len)
      (unintern (intern (format nil "A~c" (+ #\A i)) pkg) pkg))
    (check-count pkg)
    ;; assuming a rehash-size of 2.0
    (intern (format nil "A~c" (+ #\A half-len)) pkg)  ;; extend
    (check-count pkg))))

(deftest test-package-symcount ()
  (flet ((check-count (pkg)
           (assert (= (package-intsymcount pkg)
                      (- (length (package-intsymvector pkg))
                         (count 0 (package-intsymvector pkg))))
                   "Package intsymcount value does not match!")
           (assert (= (package-symcount pkg)
                      (- (length (package-symvector pkg))
                         (count 0 (package-symvector pkg))))
                   "Package symcount value does not match!")))
    (let* ((pkg (make-package (symbol-pname (gensym "TEST-PACKAGE"))))
           (half-len (/ (length (package-intsymvector pkg)) 2)))
    (dotimes (i half-len)
      (let ((sym (intern (format nil "A~c" (+ #\A i)) pkg)))
        (export sym pkg)))
    (check-count pkg)
    (dotimes (i half-len)
      (unintern (intern (format nil "A~c" (+ #\A i)) pkg) pkg))
    (check-count pkg)
    ;; assuming a rehash-size of 2.0
    (intern (format nil "A~c" (+ #\A half-len)) pkg)  ;; extend
    (check-count pkg))))


(eval-when (load eval)
  (run-all-tests)
  (exit))
