(in-package #:cl-containers-test)

(deftestsuite test-ring-buffers (cl-containers-test)
  ())

(addtest (test-ring-buffers)
  test-size
  (ensure-same (size (make-container 'ring-buffer)) 0))

(addtest (test-ring-buffers)
  test-size
  (let ((fifo (make-ring-buffer 2)))
    (ensure-same (size fifo) 0)
    (insert-item fifo 17)
    (ensure-same (size fifo) 1)))

(addtest (test-ring-buffers)
  test-reverse
  (let ((lifo (make-ring-buffer 2 :last-in-first-out)))
    (insert-item lifo 17)
    (insert-item lifo 18)
    (ensure-same (item-at lifo 0) 18)))

(addtest (test-ring-buffers)
  test-first-and-current
  (let ((lifo (make-ring-buffer 3 :last-in-first-out))
        (fifo (make-ring-buffer 3)))
    (insert-item lifo 17)
    (insert-item lifo 18)
    (insert-item lifo 19)
    (ensure-same (first-element lifo) 19)
    (ensure-same (current-item lifo) 17)
    (insert-item fifo 17)
    (insert-item fifo 18)
    (insert-item fifo 19)
    (ensure-same (first-element fifo) 17)
    (ensure-same (current-item fifo) 19)))

(addtest (test-ring-buffers)
  test-wrap-over
  (let ((lifo (make-ring-buffer 3 :last-in-first-out))
        (fifo (make-ring-buffer 3)))
    (insert-item lifo 17)
    (insert-item lifo 18)
    (insert-item lifo 19)
    (insert-item lifo 20)
    (ensure-same (first-element lifo) 20)
    (ensure-same (current-item lifo) 18)
    (insert-item fifo 17)
    (insert-item fifo 18)
    (insert-item fifo 19)
    (insert-item fifo 20)
    (ensure-same (first-element fifo) 18)
    (ensure-same (current-item fifo) 20)))

(addtest (test-ring-buffers)
  test-index-wrap-over
  (let ((lifo (make-ring-buffer 3 :last-in-first-out))
        (fifo (make-ring-buffer 3)))
    (insert-item lifo 17)
    (insert-item lifo 18)
    (ensure-same (item-at lifo 0) 18)
    (ensure-same (item-at lifo 1) 17)
    (ensure-same (item-at lifo 0) 18)
    (insert-item fifo 17)
    (insert-item fifo 18)
    (ensure-same (item-at fifo 0) 17)
    (ensure-same (item-at fifo 1) 18)
    (ensure-same (item-at fifo 2) 17)))

(addtest (test-ring-buffers)
  test-list-conversion
  (let ((lifo (make-ring-buffer 3 :last-in-first-out))
        (fifo (make-ring-buffer 3)))
    (insert-item lifo 17)
    (insert-item lifo 18)
    (insert-item lifo 19)
    (ensure-same (container->list lifo) '(19 18 17))
    (insert-item fifo 17)
    (insert-item fifo 18)
    (insert-item fifo 19)
    (ensure-same (container->list fifo) '(17 18 19))))

(addtest (test-ring-buffers)
  test-delete-first
  (let ((lifo (make-ring-buffer 3 :last-in-first-out))
        (fifo (make-ring-buffer 3)))
    (insert-item lifo 17)
    (insert-item lifo 18)
    (insert-item lifo 19)
    (delete-first lifo)
    (ensure-same (container->list lifo) '(18 17))
    (insert-item fifo 17)
    (insert-item fifo 18)
    (insert-item fifo 19)
    (delete-first fifo)
    (ensure-same (container->list fifo) '(18 19))))

(addtest (test-ring-buffers)
  test-empty!
  (let ((lifo (make-ring-buffer 3 :last-in-first-out))
        (fifo (make-ring-buffer 3)))
    (insert-item lifo 17)
    (insert-item lifo 18)
    (insert-item lifo 19)
    (empty! lifo)
    (ensure-same (container->list lifo) '())
    (ensure-same (size lifo) 0)
    (insert-item fifo 17)
    (insert-item fifo 18)
    (insert-item fifo 19)
    (empty! fifo)
    (ensure-same (container->list fifo) '())
    (ensure-same (size fifo) 0)))

(addtest (test-ring-buffers)
  test-iterate
  (let ((lifo (make-ring-buffer 3 :last-in-first-out))
        (lifo-list '())
        (fifo (make-ring-buffer 3))
        (fifo-list '()))
    (insert-item lifo 17)
    (insert-item lifo 18)
    (insert-item lifo 19)
    (iterate-nodes lifo (lambda (n) (push n lifo-list)))
    (ensure-same (container->list lifo) (reverse lifo-list))
    (insert-item fifo 17)
    (insert-item fifo 18)
    (insert-item fifo 19)
    (iterate-nodes fifo (lambda (n) (push n fifo-list)))
    (ensure-same (container->list fifo) (reverse fifo-list))))

(addtest (test-ring-buffers)
  test-delete
  (let ((lifo (make-ring-buffer 3 :last-in-first-out))
        (lifo-list '())
        (fifo (make-ring-buffer 3))
        (fifo-list '()))
    (insert-item lifo 17)
    (insert-item lifo 18)
    (insert-item lifo 19)
    (delete-item-at lifo 1)
    (ensure-same (size lifo) 2)
    (ensure-same (item-at lifo 1) 17)
    (ensure-same (item-at lifo 0) 19)
    (delete-item-at lifo 1)
    (ensure-same (size lifo) 1)
    (ensure-same (item-at lifo 0) 19)

    (insert-item fifo 17)
    (insert-item fifo 18)
    (insert-item fifo 19)
    (delete-item-at fifo 1)
    (ensure-same (size fifo) 2)
    (ensure-same (item-at fifo 0) 17)
    (ensure-same (item-at fifo 1) 19)
    (delete-item-at fifo 1)
    (ensure-same (size fifo) 1)
    (ensure-same (item-at fifo 0) 17)))
