Is this a bug? NullPointerException when trying to generate from s/or spec which includes nil

165 Views Asked by At

I found a way to throw NullPointerExceptions by generating values using an s/or spec. I want to be able to generate and label a nil value, no s/nilable isn't suitable.

Is this a bug in clojure.spec?

(ns blah
  (:require [clojure.spec.alpha :as s])) 

(s/def ::fine (s/or :int int? :nil nil?)
(s/def ::throws (s/or :int (s/int-in 1 5) :zero zero? :nil nil?)

(s/exercise ::fine)
=>
([nil [:nil nil]
 [-1 [:int -1]]
 [nil [:nil nil]]
 [0 [:int 0]]
 [nil [:nil nil]]
 [15 [:int 15]]
 [-25 [:int -25]]
 [nil [:nil nil]]
 [-2 [:int -2]]
 [-30 [:int -30]]])]])

(s/exercise ::throws)
=>
NullPointerException   clojure.lang.Numbers.ops (Numbers.java:1018)

If you limit the number of times ::throws is exercised, you see correct :int and :zero values, it's the :nil which throws.

1

There are 1 best solutions below

4
On BEST ANSWER

This works:

(s/def ::works (s/or :int (s/int-in 1 5) :nil nil? :zero zero?))

I assume spec will try to conform in order of the or alternatives. Conforming nil using the zero? predicate will crash, but moving nil? in front of that, will prevent that from happening.

What also works is using a set instead of a predicate:

(s/def ::throws (s/or :int (s/int-in 1 5) :zero #{0} :nil nil?))