diff --git a/.github/workflows/clojure-linting.yaml b/.github/workflows/clojure-linting.yaml new file mode 100644 index 00000000..cca5cb67 --- /dev/null +++ b/.github/workflows/clojure-linting.yaml @@ -0,0 +1,30 @@ +name: Clojure Linting + +on: + pull_request: + types: [opened, reopened, edited, synchronize] + paths: ['src/**','test/**','.clj-kondo/config.edn','project.clj','.github/**'] + +jobs: + clojure-linting: + name: Clojure Linting + runs-on: ubuntu-latest + steps: + - name: setup java + uses: actions/setup-java@v3 + with: + distribution: temurin + java-version: 17 + - name: checkout repo + uses: actions/checkout@v2 + - name: install clj-kondo (this is quite fast) + run: | + curl -sLO https://raw.githubusercontent.com/clj-kondo/clj-kondo/master/script/install-clj-kondo + chmod +x install-clj-kondo + ./install-clj-kondo --dir . + - name: kondo lint + run: ./clj-kondo --lint src test + - name: eastwood lint + run: | + java -version + lein eastwood \ No newline at end of file diff --git a/.github/workflows/lein-test.yaml b/.github/workflows/lein-test.yaml new file mode 100644 index 00000000..8f5bab43 --- /dev/null +++ b/.github/workflows/lein-test.yaml @@ -0,0 +1,29 @@ +name: PR Testing + +on: + workflow_dispatch: + pull_request: + types: [opened, reopened, edited, synchronize] + paths: ['src/**','test/**','project.clj'] + +jobs: + pr-testing: + name: PR Testing + strategy: + fail-fast: false + matrix: + version: ['8', '11', '17'] + runs-on: ubuntu-latest + steps: + - name: checkout repo + uses: actions/checkout@v3 + with: + submodules: recursive + - name: setup java + uses: actions/setup-java@v3 + with: + distribution: 'temurin' + java-version: ${{ matrix.version }} + - name: clojure tests + run: lein test + timeout-minutes: 30 \ No newline at end of file diff --git a/CHANGELOG.md b/CHANGELOG.md index bc688da6..95019f6d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,7 @@ +## 3.3.2 +* this is a minor release changing a test utility +* adds a new arity to `logged?` that removes the restriction that only one log line must match the pattern, adds printing to the function and repo documentation to make users aware of this single line match restriction + ## 3.3.1 This is a minor dependency change release diff --git a/documentation/Test-Utils.md b/documentation/Test-Utils.md index 374dd7db..b60a227e 100644 --- a/documentation/Test-Utils.md +++ b/documentation/Test-Utils.md @@ -44,11 +44,15 @@ since the beginning of the form. See the `logged?` docstring for a complete description, but as an example, if the first argument is a regex pattern (typically generated via Clojure's `#"pattern"`), then `logged?` will return true if the -pattern matches the message of anything that has been logged since the -beginning of the enclosing `with-test-logging` form. An optional +pattern matches a single message of anything that has been logged since the +beginning of the enclosing `with-test-logging` form. An optional second parameter restricts the match to log events with the specified level: `:trace`, `:debug`, `:info`, `:warn`, `:error` or `:fatal`. +Note: by default `logged?` returns true only if there is exactly one +log line match. An optional third parameter can be specified to disable +this restriction. + ### `event->map` This function converts a LogEvent to a Clojure map of the kind diff --git a/test/puppetlabs/trapperkeeper/logging_test.clj b/test/puppetlabs/trapperkeeper/logging_test.clj index c13b62bf..a3f090f9 100644 --- a/test/puppetlabs/trapperkeeper/logging_test.clj +++ b/test/puppetlabs/trapperkeeper/logging_test.clj @@ -37,6 +37,23 @@ (is (true? @done?)) (is (logged? #"test thread" :info)))))) +(deftest with-test-logging-and-duplicate-log-lines + (testing "test-logging captures matches duplicate lines when specified" + (with-test-logging + (log/error "duplicate message") + (log/error "duplicate message") + (log/warn "duplicate message") + (log/warn "single message") + (testing "single line only match" + (is (not (logged? #"duplicate message"))) ;; original behavior of the fn, default behavior + (is (logged? #"duplicate message" :warn false))) + (testing "disabling single line match, enabling multiple line match" + (is (logged? #"duplicate message" :error true)) + (is (logged? #"duplicate message" nil true)) + (testing "still handles single matches" + (is (logged? #"single message" nil true)) + (is (logged? #"single message" :warn true))))))) + (deftest test-logging-configuration (testing "Calling `configure-logging!` with a logback.xml file" (configure-logging! "./dev-resources/logging/logback-debug.xml") diff --git a/test/puppetlabs/trapperkeeper/testutils/logging.clj b/test/puppetlabs/trapperkeeper/testutils/logging.clj index 7b0c047c..e932c7e4 100644 --- a/test/puppetlabs/trapperkeeper/testutils/logging.clj +++ b/test/puppetlabs/trapperkeeper/testutils/logging.clj @@ -320,19 +320,23 @@ (s/defn ^{:always-validate true} logged? ([msg-or-pred] (logged? msg-or-pred nil)) + ([msg-or-pred maybe-level] (logged? msg-or-pred maybe-level false)) ([msg-or-pred :- (s/conditional ifn? (s/pred ifn?) string? s/Str :else Pattern) - maybe-level :- (s/maybe (s/pred #(levels %)))] + maybe-level :- (s/maybe (s/pred #(levels %))) + disable-single-line-match-restriction :- s/Bool] (let [match? (cond (ifn? msg-or-pred) msg-or-pred (string? msg-or-pred) #(= msg-or-pred (:message %)) :else #(re-find msg-or-pred (:message %))) - one-element? #(and (seq %) (empty? (rest %))) + one-element-if-specified? #(if (and (seq %) (or disable-single-line-match-restriction (empty? (rest %)))) + true + (println "\n`logged?` warning: multiple log line matches found, but this arity expects only one match, returning false. Found matches: " % "\n")) correct-level? #(or (nil? maybe-level) (= maybe-level (:level %)))] (->> (map event->map @*test-log-events*) (filter correct-level?) (filter match?) - (one-element?))))) + (one-element-if-specified?))))) (defmethod clojure.test/assert-expr 'logged? [is-msg form] "Asserts that exactly one event in *test-log-events* has a message @@ -342,10 +346,10 @@ is specified, the message's keyword level (:info, :error, etc.) must also match. For example: (with-test-logging (log/info \"123\") (is (logged? #\"2\")))." - (assert (#{2 3} (count form))) - (let [[_ msg-or-pred level] form] + (assert (#{2 3 4} (count form))) + (let [[_ msg-or-pred level disable-single-line-restriction] form] `(let [events# @@#'puppetlabs.trapperkeeper.testutils.logging/*test-log-events*] - (if-not (logged? ~msg-or-pred ~level) + (if-not (logged? ~msg-or-pred ~level ~disable-single-line-restriction) (clojure.test/do-report {:type :fail :message ~is-msg