(defsuite
  "gensym"
  (deftest "gensym returns a symbol" (assert= true (symbol? (gensym))))
  (deftest
    "gensym default prefix is g"
    (let
      ((s (symbol-name (gensym))))
      (assert= true (string-contains? s "g"))))
  (deftest
    "gensym with prefix uses that prefix"
    (let
      ((s (symbol-name (gensym "var"))))
      (assert= "var" (substring s 0 3))))
  (deftest
    "gensym produces unique symbols"
    (let
      ((a (gensym)) (b (gensym)))
      (assert= false (= (symbol-name a) (symbol-name b)))))
  (deftest
    "gensym same prefix produces unique symbols"
    (let
      ((a (gensym "x")) (b (gensym "x")) (c (gensym "x")))
      (assert= false (= (symbol-name a) (symbol-name b)))
      (assert= false (= (symbol-name b) (symbol-name c)))))
  (deftest
    "gensym counter increases: names differ"
    (let
      ((a (gensym "k")) (b (gensym "k")))
      (assert= false (= (symbol-name a) (symbol-name b)))))
  (deftest
    "gensym no-arg and prefix-arg both unique"
    (let
      ((a (gensym)) (b (gensym "g")))
      (assert= false (= (symbol-name a) (symbol-name b)))))
  (deftest
    "string->symbol returns a symbol"
    (assert= true (symbol? (string->symbol "hello"))))
  (deftest
    "string->symbol symbol has correct name"
    (assert= "hello" (symbol-name (string->symbol "hello"))))
  (deftest
    "string->symbol empty string"
    (assert= true (symbol? (string->symbol ""))))
  (deftest
    "symbol->string returns a string"
    (assert= true (string? (symbol->string (quote foo)))))
  (deftest
    "symbol->string round-trips with string->symbol"
    (assert= "hello" (symbol->string (string->symbol "hello"))))
  (deftest
    "string->symbol/symbol->string round-trip"
    (let
      ((sym (string->symbol "my-var")))
      (assert= "my-var" (symbol->string sym))))
  (deftest
    "intern returns a symbol"
    (assert= true (symbol? (intern "foo"))))
  (deftest
    "intern same as string->symbol"
    (assert= "bar" (symbol-name (intern "bar"))))
  (deftest
    "symbol-interned? true for literal symbols"
    (assert= true (symbol-interned? (quote hello))))
  (deftest
    "symbol-interned? true for gensym'd symbol"
    (assert= true (symbol-interned? (gensym "g"))))
  (deftest
    "symbol-interned? true for string->symbol"
    (assert= true (symbol-interned? (string->symbol "test"))))
  (deftest
    "multiple gensym calls all unique"
    (let
      ((syms (map (fn (i) (gensym "t")) (in-range 5))))
      (let
        ((names (map symbol-name syms)))
        (let
          ((unique-names (reduce (fn (acc n) (if (some (fn (x) (= x n)) acc) acc (cons n acc))) (list) names)))
          (assert-equal 5 (len unique-names)))))))
