Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 28 additions & 0 deletions .github/workflows/jepsen-test.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
on: [ push ]

concurrency:
group: ${{ github.workflow }}-${{ github.ref }}-jepsen-test

name: Jepsen Test
permissions:
contents: read
jobs:
test:
runs-on: ubuntu-latest
env:
RUN_JEPSEN: ${{ secrets.RUN_JEPSEN }}
steps:
- uses: actions/checkout@v5
- uses: actions/setup-java@v4
with:
distribution: temurin
java-version: '21'
- name: Install Leiningen
run: |
curl -L https://raw.githubusercontent.com/technomancy/leiningen/stable/bin/lein > ~/lein
chmod +x ~/lein
~/lein version
- name: Run Jepsen tests
if: env.RUN_JEPSEN == 'true'
working-directory: jepsen
run: ~/lein test
7 changes: 6 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -21,4 +21,9 @@
go.work

# Built binary
elastickv
/elastickv

# Clojure/Leiningen build artifacts
jepsen/target/
jepsen/.lein-*
jepsen/.nrepl-port
15 changes: 15 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,21 @@ quit

### Development

### Running Jepsen tests

Jepsen tests live in `jepsen/`. Install Leiningen and run tests locally:

```bash
curl -L https://raw.githubusercontent.com/technomancy/leiningen/stable/bin/lein > ~/lein
chmod +x ~/lein
(cd jepsen && ~/lein test)
```

These Jepsen tests execute concurrent read and write operations while a nemesis
injects random network partitions. Jepsen's linearizability checker verifies the
history.



### Setup pre-commit hooks
```bash
Expand Down
8 changes: 8 additions & 0 deletions jepsen/project.clj
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
(defproject elastickv-jepsen "0.1.0-SNAPSHOT"
:description "Jepsen tests for Elastickv"
:repositories [["clojars" {:url "https://repo.clojars.org"}]]
:dependencies [[org.clojure/clojure "1.11.1"]
[jepsen "0.3.5"]
[redis.clients/jedis "5.1.0" :exclusions [org.slf4j/slf4j-api]]
[org.slf4j/slf4j-nop "2.0.9"]]
:main elastickv.jepsen-test)
45 changes: 45 additions & 0 deletions jepsen/src/elastickv/jepsen_test.clj
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
(ns elastickv.jepsen-test
(:gen-class)
(:require [jepsen
[core :as jepsen]
[cli :as cli]
[db :as db]
[client :as client]
[checker :as checker]]
[jepsen.checker.timeline :as timeline]
[jepsen.tests.linearizable-register :as register]
[jepsen.nemesis :as nemesis])
(:import (redis.clients.jedis Jedis)))

(defrecord RedisClient [port]
client/Client
(open! [this test node]
(assoc this :conn (Jedis. (name node) port)))
(close! [this test]
(.close (:conn this))
this)
(setup! [this test])
(teardown! [this test])
(invoke! [this test op]
(let [conn (:conn this)
value (:value op)]
(case (:f op)
:write (do (.set conn "k" (pr-str value))
(assoc op :type :ok))
:read (let [v (.get conn "k")]
(assoc op :type :ok
:value (when v (read-string v))))
(assoc op :type :fail :error :unknown-op)))))

(defn elastickv-test []
(register/test
Comment on lines +31 to +35

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[P1] Jepsen workflow assumes a ready-made cluster

The new Jepsen test defines nodes "n1", "n2", and "n3" with :db db/noop, so the client immediately tries to SSH and open Redis connections to those hosts without starting Elastickv anywhere. The GitHub workflow introduced in the same commit simply runs ~/lein test, but it never provisions these nodes, launches Elastickv processes, or provides SSH connectivity. As a result, every push will execute tests that cannot even start and the workflow will fail deterministically. Consider spinning up the cluster (e.g., via Docker or the demo server) before invoking the tests or gating the workflow until a deployable setup exists.

Useful? React with 👍 / 👎.

{:name "elastickv-register"
:nodes ["n1" "n2" "n3"]
:db db/noop
:client (->RedisClient 63791)
:concurrency 5
:nemesis (nemesis/partition-random-halves)}))

(defn -main
[& args]
(cli/run! (cli/single-test-cmd {:test-fn elastickv-test}) args))
6 changes: 6 additions & 0 deletions jepsen/test/elastickv/jepsen_test_test.clj
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
(ns elastickv.jepsen-test-test
(:require [clojure.test :refer :all]
[elastickv.jepsen-test :as jt]))

(deftest builds-test-spec
(is (map? (jt/elastickv-test))))
Loading