Merge branch 'array-play' into bitset

This commit is contained in:
Michiel Borkent 2022-02-13 11:39:00 +01:00
commit 7ee76646ae
171 changed files with 14325 additions and 848 deletions

View file

@ -2,5 +2,5 @@
:deps {borkdude/gh-release-artifact
#_{:local/root "../gh-release-artifact"}
{:git/url "https://github.com/borkdude/gh-release-artifact"
:sha "2f8898d84126a4e922c490f8614211a8b0cf67cd"}}
:sha "f34f3e382e6a0ef7f52748b2f27eb681f799a822"}}
:tasks {release-artifact babashka.release-artifact/release}}

View file

@ -55,11 +55,10 @@ jobs:
VERSION=$(cat resources/BABASHKA_VERSION)
jar=target/babashka-$VERSION-standalone.jar
cp $jar /tmp/release
java -jar $jar script/reflection.clj
reflection="babashka-$VERSION-reflection.json"
BABASHKA_EDN=".build/bb.edn" java -jar "$jar" release-artifact "$jar"
BABASHKA_EDN=".build/bb.edn" java -jar "$jar" release-artifact "$reflection"
java -jar "$jar" --config .build/bb.edn --deps-root . release-artifact "$jar"
java -jar "$jar" --config .build/bb.edn --deps-root . release-artifact "$reflection"
- store_artifacts:
path: /tmp/release
destination: release
@ -73,8 +72,8 @@ jobs:
working_directory: ~/repo
environment:
LEIN_ROOT: "true"
GRAALVM_VERSION: "21.3.0"
GRAALVM_HOME: /home/circleci/graalvm-ce-java11-21.3.0
GRAALVM_VERSION: "22.0.0.2"
GRAALVM_HOME: /home/circleci/graalvm-ce-java11-22.0.0.2
BABASHKA_PLATFORM: linux # used in release script
BABASHKA_TEST_ENV: native
BABASHKA_XMX: "-J-Xmx6500m"
@ -124,7 +123,7 @@ jobs:
- save_cache:
paths:
- ~/.m2
- ~/graalvm-ce-java11-21.3.0
- ~/graalvm-ce-java11-22.0.0.2
key: linux-{{ checksum "project.clj" }}-{{ checksum ".circleci/config.yml" }}
- store_artifacts:
path: /tmp/release
@ -139,8 +138,8 @@ jobs:
working_directory: ~/repo
environment:
LEIN_ROOT: "true"
GRAALVM_VERSION: "21.3.0"
GRAALVM_HOME: /home/circleci/graalvm-ce-java11-21.3.0
GRAALVM_VERSION: "22.0.0.2"
GRAALVM_HOME: /home/circleci/graalvm-ce-java11-22.0.0.2
BABASHKA_PLATFORM: linux # used in release script
BABASHKA_TEST_ENV: native
BABASHKA_STATIC: "true"
@ -203,7 +202,7 @@ jobs:
- save_cache:
paths:
- ~/.m2
- ~/graalvm-ce-java11-21.3.0
- ~/graalvm-ce-java11-22.0.0.2
key: linux-{{ checksum "project.clj" }}-{{ checksum ".circleci/config.yml" }}
- store_artifacts:
path: /tmp/release
@ -220,8 +219,8 @@ jobs:
working_directory: ~/repo
environment:
LEIN_ROOT: "true"
GRAALVM_VERSION: "21.3.0"
GRAALVM_HOME: /home/circleci/graalvm-ce-java11-21.3.0
GRAALVM_VERSION: "22.0.0.2"
GRAALVM_HOME: /home/circleci/graalvm-ce-java11-22.0.0.2
BABASHKA_PLATFORM: linux # used in release script
BABASHKA_ARCH: aarch64
BABASHKA_TEST_ENV: native
@ -271,7 +270,7 @@ jobs:
- save_cache:
paths:
- ~/.m2
- ~/graalvm-ce-java11-21.3.0
- ~/graalvm-ce-java11-22.0.0.2
key: linux-aarch64-{{ checksum "project.clj" }}-{{ checksum ".circleci/config.yml" }}
- store_artifacts:
path: /tmp/release
@ -288,8 +287,8 @@ jobs:
working_directory: ~/repo
environment:
LEIN_ROOT: "true"
GRAALVM_VERSION: "21.3.0"
GRAALVM_HOME: /home/circleci/graalvm-ce-java11-21.3.0
GRAALVM_VERSION: "22.0.0.2"
GRAALVM_HOME: /home/circleci/graalvm-ce-java11-22.0.0.2
BABASHKA_PLATFORM: linux # used in release script
BABASHKA_ARCH: aarch64
BABASHKA_TEST_ENV: native
@ -349,7 +348,7 @@ jobs:
- save_cache:
paths:
- ~/.m2
- ~/graalvm-ce-java11-21.3.0
- ~/graalvm-ce-java11-22.0.0.2
key: linux-aarch64-{{ checksum "project.clj" }}-{{ checksum ".circleci/config.yml" }}
- store_artifacts:
path: /tmp/release
@ -363,8 +362,8 @@ jobs:
xcode: "12.0.0"
environment:
MACOSX_DEPLOYMENT_TARGET: 10.13 # 10.12 is EOL
GRAALVM_VERSION: "21.3.0"
GRAALVM_HOME: /Users/distiller/graalvm-ce-java11-21.3.0/Contents/Home
GRAALVM_VERSION: "22.0.0.2"
GRAALVM_HOME: /Users/distiller/graalvm-ce-java11-22.0.0.2/Contents/Home
BABASHKA_PLATFORM: macos # used in release script
BABASHKA_TEST_ENV: native
BABASHKA_XMX: "-J-Xmx6500m"
@ -411,7 +410,7 @@ jobs:
- save_cache:
paths:
- ~/.m2
- ~/graalvm-ce-java11-21.3.0/Contents/Home
- ~/graalvm-ce-java11-22.0.0.2/Contents/Home
key: mac-{{ checksum "project.clj" }}-{{ checksum ".circleci/config.yml" }}
- store_artifacts:
path: /tmp/release
@ -479,7 +478,7 @@ workflows:
- docker:
filters:
branches:
only:
only:
- master
requires:
- linux

View file

@ -6,6 +6,15 @@ image_name="babashka/babashka"
image_tag=$(cat resources/BABASHKA_VERSION)
platform=${PLATFORM:-"linux/amd64"}
latest_tag="latest"
label_args=("--label" "'org.opencontainers.image.description=Native, fast starting Clojure interpreter for scripting'"
"--label" "org.opencontainers.image.title=Babashka"
"--label" "org.opencontainers.image.created=$(date -Iseconds)"
"--label" "org.opencontainers.image.url=${CIRCLE_REPOSITORY_URL}"
"--label" "org.opencontainers.image.documentation=${CIRCLE_REPOSITORY_URL}"
"--label" "org.opencontainers.image.source=${CIRCLE_REPOSITORY_URL}"
"--label" "org.opencontainers.image.revision=${CIRCLE_SHA1}"
"--label" "org.opencontainers.image.ref.name=${CIRCLE_TAG}:${CIRCLE_BRANCH}"
"--label" "org.opencontainers.image.version=${image_tag}")
if [[ $image_tag =~ SNAPSHOT$ ]]; then
echo "This is a snapshot version"
@ -24,28 +33,26 @@ if [ -z "$CIRCLE_PULL_REQUEST" ] && [ "$CIRCLE_BRANCH" = "master" ]; then
if [[ $tarball_platform == "linux-arm64" ]]; then tarball_platform="linux-aarch64"; fi
mkdir -p $p
tar zxvf "/tmp/release/babashka-${image_tag}-${tarball_platform}.tar.gz" -C $p
# this overwrites, but this is to work around having built the uberjar/metabom multiple times
cp "/tmp/release/${tarball_platform}-metabom.jar" ./metabom.jar
done
docker buildx build -t "$image_name:$image_tag" --platform "$platform" --push -f Dockerfile.ci .
docker buildx build -t "$image_name:$image_tag" --platform "$platform" "${label_args[@]}" --push -f Dockerfile.ci .
if [[ $snapshot == "false" ]]; then
echo "Building & pushing $platform Docker image(s) $image_name:$latest_tag"
docker buildx build -t "$image_name:$latest_tag" --platform "$platform" --push -f Dockerfile.ci .
docker buildx build -t "$image_name:$latest_tag" --platform "$platform" "${label_args[@]}" --push -f Dockerfile.ci .
fi
for p in "${platforms[@]}"; do
rm -rf $p
done
# alpine doesn't provide upstream arm64 images yet
if [[ $platform == "linux-amd64" ]]; then
tar zxvf "/tmp/release/babashka-${image_tag}-${platform}-static.tar.gz"
docker build -t "$image_name:alpine" -f Dockerfile.alpine .
rm -f bb
docker tag "$image_name:alpine" "$image_name:$image_tag-alpine"
echo "Pushing image $image_name:$image_tag-alpine"
docker push "$image_name:$image_tag-alpine"
if [[ $snapshot == "false" ]]; then
echo "Pushing image $image_name:alpine"
docker push "$image_name:alpine"
fi
# build alpine image for linux-amd64 only (no upstream arm64 support yet)
tar zxvf "/tmp/release/babashka-${image_tag}-linux-amd64-static.tar.gz"
echo "Building & pushing Docker image $image_name:$image_tag-alpine"
docker buildx build -t "$image_name:$image_tag-alpine" --platform=linux/amd64 "${label_args[@]}" --push -f Dockerfile.alpine .
if [[ $snapshot == "false" ]]; then
echo "Building & pushing Docker image $image_name:alpine"
docker buildx build -t "$image_name:alpine" --platform=linux/amd64 "${label_args[@]}" --push -f Dockerfile.alpine .
fi
else
echo "Not publishing Docker image"

View file

@ -6,9 +6,7 @@ cp bb /tmp/release
VERSION=$(cat resources/BABASHKA_VERSION)
cd /tmp/release
mkdir -p /tmp/bb_size
./bb '(spit "/tmp/bb_size/size" (.length (io/file "bb")))'
## release binary as tar.gz archive
@ -18,13 +16,20 @@ if [ "$BABASHKA_STATIC" = "true" ]; then
arch="$arch-static"
fi
# because circle won't allow the same file to be saved/restored in the same workspace concurrently
cp metabom.jar "/tmp/release/$BABASHKA_PLATFORM-$arch-metabom.jar"
cd /tmp/release
mkdir -p /tmp/bb_size
./bb '(spit "/tmp/bb_size/size" (.length (io/file "bb")))'
archive="babashka-$VERSION-$BABASHKA_PLATFORM-$arch.tar.gz"
tar zcvf "$archive" bb # bbk
cd -
BABASHKA_EDN=".build/bb.edn" ./bb release-artifact "/tmp/release/$archive"
./bb --config .build/bb.edn --deps-root . release-artifact "/tmp/release/$archive"
## cleanup

View file

@ -0,0 +1 @@
{:lint-as {babashka.fs/with-temp-dir clojure.core/let}}

2
.dir-locals.el Normal file
View file

@ -0,0 +1,2 @@
((clojure-mode
(cider-clojure-cli-aliases . "test")))

View file

@ -45,17 +45,17 @@ jobs:
uses: actions/cache@v1
id: cache-graalvm
with:
path: ~/graalvm-ce-java11-21.3.0
key: ${{ runner.os }}-graalvm-21.3.0
path: ~/graalvm-ce-java11-22.0.0.2
key: ${{ runner.os }}-graalvm-22.0.0.2
restore-keys: |
${{ runner.os }}-graalvm-21.3.0
${{ runner.os }}-graalvm-22.0.0.2
- name: Download GraalVM
run: |
cd ~
if ! [ -d graalvm-ce-java11-21.3.0 ]; then
curl -O -sL https://github.com/graalvm/graalvm-ce-builds/releases/download/vm-21.3.0/graalvm-ce-java11-linux-amd64-21.3.0.tar.gz
tar xzf graalvm-ce-java11-linux-amd64-21.3.0.tar.gz
if ! [ -d graalvm-ce-java11-22.0.0.2 ]; then
curl -O -sL https://github.com/graalvm/graalvm-ce-builds/releases/download/vm-22.0.0.2/graalvm-ce-java11-linux-amd64-22.0.0.2.tar.gz
tar xzf graalvm-ce-java11-linux-amd64-22.0.0.2.tar.gz
fi
- name: Fetch deps
@ -65,18 +65,18 @@ jobs:
- name: Run tests
run: |
export GRAALVM_HOME="$HOME/graalvm-ce-java11-21.3.0"
export GRAALVM_HOME="$HOME/graalvm-ce-java11-22.0.0.2"
script/test
- name: Test libraries
run: |
export GRAALVM_HOME="$HOME/graalvm-ce-java11-21.3.0"
export GRAALVM_HOME="$HOME/graalvm-ce-java11-22.0.0.2"
sudo script/install-clojure
script/run_lib_tests
- name: Build uberjar
run: |
export GRAALVM_HOME="$HOME/graalvm-ce-java11-21.3.0"
export GRAALVM_HOME="$HOME/graalvm-ce-java11-22.0.0.2"
script/uberjar
- name: Babashka version
@ -119,17 +119,17 @@ jobs:
uses: actions/cache@v1
id: cache-graalvm
with:
path: ~/graalvm-ce-java11-21.3.0
key: ${{ runner.os }}-graalvm-21.3.0
path: ~/graalvm-ce-java11-22.0.0.2
key: ${{ runner.os }}-graalvm-22.0.0.2
restore-keys: |
${{ runner.os }}-graalvm-21.3.0
${{ runner.os }}-graalvm-22.0.0.2
- name: Download GraalVM
run: |
cd ~
if ! [ -d graalvm-ce-java11-21.3.0 ]; then
curl -O -sL https://github.com/graalvm/graalvm-ce-builds/releases/download/vm-21.3.0/graalvm-ce-java11-linux-amd64-21.3.0.tar.gz
tar xzf graalvm-ce-java11-linux-amd64-21.3.0.tar.gz
if ! [ -d graalvm-ce-java11-22.0.0.2 ]; then
curl -O -sL https://github.com/graalvm/graalvm-ce-builds/releases/download/vm-22.0.0.2/graalvm-ce-java11-linux-amd64-22.0.0.2.tar.gz
tar xzf graalvm-ce-java11-linux-amd64-22.0.0.2.tar.gz
fi
- name: Babashka version
@ -142,12 +142,12 @@ jobs:
run: |
export BABASHKA_JAR=babashka-${{ steps.babashka-version.outputs.version }}-standalone.jar
export BABASHKA_XMX="-J-Xmx6g"
export GRAALVM_HOME="$HOME/graalvm-ce-java11-21.3.0"
export GRAALVM_HOME="$HOME/graalvm-ce-java11-22.0.0.2"
script/compile
- name: Test binary
run: |
export GRAALVM_HOME="$HOME/graalvm-ce-java11-21.3.0"
export GRAALVM_HOME="$HOME/graalvm-ce-java11-22.0.0.2"
BABASHKA_TEST_ENV=native script/test
- name: Install clojure
@ -156,7 +156,7 @@ jobs:
- name: Test libraries
run: |
export GRAALVM_HOME="$HOME/graalvm-ce-java11-21.3.0"
export GRAALVM_HOME="$HOME/graalvm-ce-java11-22.0.0.2"
BABASHKA_TEST_ENV=native script/run_lib_tests
- name: Upload artifact
@ -194,17 +194,17 @@ jobs:
uses: actions/cache@v1
id: cache-graalvm
with:
path: ~/graalvm-ce-java11-21.3.0
key: ${{ runner.os }}-graalvm-21.3.0
path: ~/graalvm-ce-java11-22.0.0.2
key: ${{ runner.os }}-graalvm-22.0.0.2
restore-keys: |
${{ runner.os }}-graalvm-21.3.0
${{ runner.os }}-graalvm-22.0.0.2
- name: Download GraalVM
run: |
cd ~
if ! [ -d graalvm-ce-java11-21.3.0 ]; then
curl -O -sL https://github.com/graalvm/graalvm-ce-builds/releases/download/vm-21.3.0/graalvm-ce-java11-linux-amd64-21.3.0.tar.gz
tar xzf graalvm-ce-java11-linux-amd64-21.3.0.tar.gz
if ! [ -d graalvm-ce-java11-22.0.0.2 ]; then
curl -O -sL https://github.com/graalvm/graalvm-ce-builds/releases/download/vm-22.0.0.2/graalvm-ce-java11-linux-amd64-22.0.0.2.tar.gz
tar xzf graalvm-ce-java11-linux-amd64-22.0.0.2.tar.gz
fi
- name: Babashka version
@ -217,14 +217,14 @@ jobs:
run: |
export BABASHKA_JAR=babashka-${{ steps.babashka-version.outputs.version }}-standalone.jar
export BABASHKA_XMX="-J-Xmx6g"
export GRAALVM_HOME="$HOME/graalvm-ce-java11-21.3.0"
export GRAALVM_HOME="$HOME/graalvm-ce-java11-22.0.0.2"
export BABASHKA_STATIC=true
script/compile
- name: Test binary
run: |
./bb '(+ 1 2 3)'
export GRAALVM_HOME="$HOME/graalvm-ce-java11-21.3.0"
export GRAALVM_HOME="$HOME/graalvm-ce-java11-22.0.0.2"
BABASHKA_TEST_ENV=native script/test
- name: Install clojure
@ -233,7 +233,7 @@ jobs:
- name: Test libraries
run: |
export GRAALVM_HOME="$HOME/graalvm-ce-java11-21.3.0"
export GRAALVM_HOME="$HOME/graalvm-ce-java11-22.0.0.2"
BABASHKA_TEST_ENV=native script/run_lib_tests
- name: Upload artifact
@ -262,17 +262,17 @@ jobs:
uses: actions/cache@v1
id: cache-graalvm
with:
path: ~/graalvm-ce-java11-21.3.0
key: ${{ runner.os }}-graalvm-21.3.0
path: ~/graalvm-ce-java11-22.0.0.2
key: ${{ runner.os }}-graalvm-22.0.0.2
restore-keys: |
${{ runner.os }}-graalvm-21.3.0
${{ runner.os }}-graalvm-22.0.0.2
- name: Download GraalVM
run: |
cd ~
if ! [ -d graalvm-ce-java11-21.3.0 ]; then
curl -O -sL https://github.com/graalvm/graalvm-ce-builds/releases/download/vm-21.3.0/graalvm-ce-java11-darwin-amd64-21.3.0.tar.gz
tar xzf graalvm-ce-java11-darwin-amd64-21.3.0.tar.gz
if ! [ -d graalvm-ce-java11-22.0.0.2 ]; then
curl -O -sL https://github.com/graalvm/graalvm-ce-builds/releases/download/vm-22.0.0.2/graalvm-ce-java11-darwin-amd64-22.0.0.2.tar.gz
tar xzf graalvm-ce-java11-darwin-amd64-22.0.0.2.tar.gz
fi
- name: Babashka version
@ -285,18 +285,18 @@ jobs:
run: |
export BABASHKA_JAR=babashka-${{ steps.babashka-version.outputs.version }}-standalone.jar
export BABASHKA_XMX="-J-Xmx6g"
export GRAALVM_HOME="$HOME/graalvm-ce-java11-21.3.0/Contents/Home"
export GRAALVM_HOME="$HOME/graalvm-ce-java11-22.0.0.2/Contents/Home"
script/compile
- name: Test binary
run: |
export GRAALVM_HOME="$HOME/graalvm-ce-java11-21.3.0/Contents/Home"
export GRAALVM_HOME="$HOME/graalvm-ce-java11-22.0.0.2/Contents/Home"
sudo script/install-leiningen
BABASHKA_TEST_ENV=native script/test
- name: Test libraries
run: |
export GRAALVM_HOME="$HOME/graalvm-ce-java11-21.3.0/Contents/Home"
export GRAALVM_HOME="$HOME/graalvm-ce-java11-22.0.0.2/Contents/Home"
sudo script/install-clojure
BABASHKA_TEST_ENV=native script/run_lib_tests

View file

@ -4,11 +4,50 @@ For a list of breaking changes, check [here](#breaking-changes).
## Unreleased
- Fix [#1170](https://github.com/babashka/babashka/issues/1170): defmacro with a defrecord inside fails to resolve classname
## 0.7.4 (2022-01-25)
Please leave some feedback about babashka [here](https://forms.gle/ko3NjDg2SwXeEoNQ9).
- Add new namespace from clojure 1.11: `clojure.math`
- Add new vars from clojure 1.11: `abs`, `iteration`
- Add compatibility with `org.clojure/algo.monads`
- SCI: support `:as-alias`
- SCI: add `pop!` ([@kbaba1001](https://github.com/kbaba1001))
- `deps.clj`: update to clojure CLI 1.10.3.1058
- Add metabom jar to docker images [#1133](https://github.com/babashka/babashka/issues/1133) ([@kipz](https://github.com/kipz), [@lispyclouds](https://github.com/lispyclouds))
- Add opencontainers annotations to docker image [#1134](https://github.com/babashka/babashka/issues/1134) ([@kipz](https://github.com/kipz), [@lispyclouds](https://github.com/lispyclouds))
- Fix Alpine Linux Docker images in CI script [#1140](https://github.com/babashka/babashka/issues/1140) ([@kipz](https://github.com/kipz), [@lispyclouds](https://github.com/lispyclouds))
- `babashka.fs`: create dirs in `copy-tree` ([@duzunov](https://github.com/duzunov))
- SCI: fix order of metadata evaluation ([@erdos](https://github.com/erdos))
- Fix: cannot take value of macro of `->`
- Fix [#1144](https://github.com/babashka/babashka/issues/1144): cannot create multidimensional arrays
- Fix [#1143](https://github.com/babashka/babashka/issues/1143): allow optional (ignored) `--` when using using `--main` ([@grzm](https://github.com/grzm))
- SCI: throw when `recur` is used from non-tail position
- Add more libraries to CI lib tests ([@cljwalker](https://github.com/cljwalker))
- Upgrade several built-in deps: `org.clojure/clojure`, `cheshire`, `core.async`, `test.check`
## 0.7.3 (2021-12-30)
- Do not require java for bb tasks without deps [#1123](https://github.com/babashka/babashka/issues/1123), [#1124](https://github.com/babashka/babashka/issues/1124)
## 0.7.2 (2021-12-29)
- Add `spy` macro from `taoensso.timbre` [#1087](https://github.com/babashka/babashka/issues/1087)
- Better error for higher order fn arity mismatch
- Check `shasum` / `sha256sum` in `PATH` on install script ([@thiagokokada](https://github.com/thiagokokada))
- Build arm64 docker image in CI [#1099](https://github.com/babashka/babashka/issues/1099) ([@cap10morgan](https://github.com/cap10morgan))
- Upgrade to `edamame` v0.0.19
- Load tasks and deps from other bb.edn file using `--config` and `--deps-root` options [#1110](https://github.com/babashka/babashka/issues/1110)
- Uberscript improvements [#584](https://github.com/babashka/babashka/issues/584), [#1037](https://github.com/babashka/babashka/issues/1037)
- Include native elements in printed stacktrace [#1105](https://github.com/babashka/babashka/issues/1105)
- Missing error message when exception happens in REPL print [#1116](https://github.com/babashka/babashka/issues/1116)
- Undeprecate `$` in babashka.process
- Add lots of library tests to CI ([@cldwalker](https://github.com/cldwalker))
- Release SNAPSHOT builds to
[babashka-dev-builds](https://github.com/babashka/babashka-dev-builds/releases)
(use only for testing)
## 0.7.0 (2021-12-10)

View file

@ -5,7 +5,7 @@ RUN apt update
RUN apt install --no-install-recommends -yy build-essential zlib1g-dev
WORKDIR "/opt"
ENV GRAALVM_VERSION="21.3.0"
ENV GRAALVM_VERSION="22.0.0.2"
ARG TARGETARCH
ENV BABASHKA_ARCH=${TARGETARCH}
ENV GRAALVM_ARCH=${TARGETARCH}
@ -73,5 +73,6 @@ RUN ./script/compile
FROM ubuntu:latest
RUN apt-get update && apt-get install -y curl \
&& mkdir -p /usr/local/bin
COPY --from=BASE /opt/target/metabom.jar /opt/babashka-metabom.jar
COPY --from=BASE /opt/bb /usr/local/bin/bb
CMD ["bb"]

View file

@ -24,6 +24,7 @@ RUN apk --no-cache add curl ca-certificates tar && \
apk add --allow-untrusted /tmp/glibc-2.28-r0.apk
RUN echo 'hosts: files mdns4_minimal [NOTFOUND=return] dns mdns4' >> /etc/nsswitch.conf
COPY metabom.jar /opt/babashka-metabom.jar
COPY --from=tester /bin/bb /bin/bb
CMD ["bb"]

View file

@ -7,6 +7,7 @@ RUN apt-get update \
ARG TARGETARCH
ARG TARGETOS
COPY metabom.jar /opt/babashka-metabom.jar
COPY ${TARGETOS}/${TARGETARCH}/bb /usr/local/bin/bb
RUN chmod +x /usr/local/bin/bb

View file

@ -147,6 +147,11 @@ Install:
brew install borkdude/brew/babashka
On macOS with an M1 processor:
softwareupdate --install-rosetta
arch -x86_64 brew install borkdude/brew/babashka
Upgrade:
brew upgrade babashka

View file

@ -7,8 +7,8 @@ image: Visual Studio 2017
clone_folder: C:\projects\babashka
environment:
GRAALVM_HOME: C:\projects\babashka\graalvm\graalvm-ce-java11-21.3.0
JAVA_HOME: C:\projects\babashka\graalvm\graalvm-ce-java11-21.3.0
GRAALVM_HOME: C:\projects\babashka\graalvm\graalvm-ce-java11-22.0.0.2
JAVA_HOME: C:\projects\babashka\graalvm\graalvm-ce-java11-22.0.0.2
BABASHKA_XMX: "-J-Xmx5g"
cache:
@ -33,7 +33,7 @@ clone_script:
build_script:
- cmd: >-
powershell -Command "if (Test-Path('graalvm')) { return } else { (New-Object Net.WebClient).DownloadFile('https://github.com/graalvm/graalvm-ce-builds/releases/download/vm-21.3.0/graalvm-ce-java11-windows-amd64-21.3.0.zip', 'graalvm.zip') }"
powershell -Command "if (Test-Path('graalvm')) { return } else { (New-Object Net.WebClient).DownloadFile('https://github.com/graalvm/graalvm-ce-builds/releases/download/vm-22.0.0.2/graalvm-ce-java11-windows-amd64-22.0.0.2.zip', 'graalvm.zip') }"
powershell -Command "if (Test-Path('graalvm')) { return } else { Expand-Archive graalvm.zip graalvm }"
@ -62,11 +62,7 @@ build_script:
jar -cMf %zip% bb.exe
set BABASHKA_EDN=.build/bb.edn
bb release-artifact %zip%
set BABASHKA_EDN=
bb --config .build/bb.edn --deps-root . release-artifact %zip%
set BABASHKA_CLASSPATH=

@ -1 +1 @@
Subproject commit 6f51f783a91b0cfab2663b55607b45e9e342bcb6
Subproject commit e4a47f6ba6ea91c898c68fcea0358260deea7a4d

View file

@ -14,20 +14,20 @@
"depstar/src" "process/src"
"deps.clj/src" "deps.clj/resources"
"resources" "sci/resources"],
:deps {org.clojure/clojure {:mvn/version "1.11.0-alpha3"},
:deps {org.clojure/clojure {:mvn/version "1.11.0-beta1"},
borkdude/sci {:local/root "sci"}
babashka/babashka.curl {:local/root "babashka.curl"}
babashka/fs {:local/root "fs"}
babashka/babashka.core {:local/root "babashka.core"}
borkdude/graal.locking {:mvn/version "0.0.2"},
org.clojure/core.async {:mvn/version "1.4.627"},
org.clojure/core.async {:mvn/version "1.5.648"},
org.clojure/tools.cli {:mvn/version "1.0.206"},
org.clojure/data.csv {:mvn/version "1.0.0"},
cheshire/cheshire {:mvn/version "5.10.1"}
cheshire/cheshire {:mvn/version "5.10.2"}
org.clojure/data.xml {:mvn/version "0.2.0-alpha6"}
clj-commons/clj-yaml {:mvn/version "0.7.107"}
com.cognitect/transit-clj {:mvn/version "1.0.324"}
org.clojure/test.check {:mvn/version "1.1.0"}
com.cognitect/transit-clj {:mvn/version "1.0.329"}
org.clojure/test.check {:mvn/version "1.1.1"}
nrepl/bencode {:mvn/version "1.1.0"}
seancorfield/next.jdbc {:mvn/version "1.1.610"}
org.postgresql/postgresql {:mvn/version "42.2.18"}
@ -55,10 +55,7 @@
:extra-deps {org.clj-commons/clj-http-lite {:mvn/version "0.4.392"}
org.babashka/spec.alpha {:git/url "https://github.com/babashka/spec.alpha"
:sha "0dec1f88cbde74a0470b454396f09a03adb4ae39"}
lambdaisland/regal {:git/url "https://github.com/lambdaisland/regal"
:sha "f902d2c43121f9e1c48603d6eb99f5900eb6a9f6"}
weavejester/medley {:git/url "https://github.com/weavejester/medley"
:sha "a4e5fb5383f5c0d83cb2d005181a35b76d8a136d"}
lambdaisland/regal {:mvn/version "0.0.143"}
cprop/cprop {:mvn/version "0.1.16"}
comb/comb {:mvn/version "0.1.1"}
mvxcvi/arrangement {:mvn/version "2.0.0"}
@ -69,16 +66,16 @@
henryw374/cljc.java-time
{:git/url "https://github.com/henryw374/cljc.java-time.git"
:sha "e3d184b78e933322b3fcaa6ca66cbb8f42a6b35c"}
camel-snake-kebab/camel-snake-kebab {:mvn/version "0.4.1"}
camel-snake-kebab/camel-snake-kebab {:mvn/version "0.4.2"}
aero/aero {:mvn/version "1.1.6"}
org.clojure/data.generators {:mvn/version "1.0.0"}
honeysql/honeysql {:mvn/version "1.0.444"}
com.github.seancorfield/honeysql {:mvn/version "2.0.0-rc2"}
minimallist/minimallist {:mvn/version "0.0.6"}
circleci/bond {:mvn/version "0.4.0"}
version-clj/version-clj {:mvn/version "2.0.1"}
honeysql/honeysql {:mvn/version "1.0.461"}
com.github.seancorfield/honeysql {:mvn/version "2.2.840"}
minimallist/minimallist {:mvn/version "0.0.10"}
circleci/bond {:mvn/version "0.6.0"}
version-clj/version-clj {:mvn/version "2.0.2"}
gaka/gaka {:mvn/version "0.3.0"}
failjure/failjure {:mvn/version "2.1.1"}
failjure/failjure {:mvn/version "2.2.0"}
io.helins/binf {:mvn/version "1.1.0-beta0"}
rm-hull/jasentaa {:mvn/version "0.2.5"}
slingshot/slingshot {:mvn/version "0.12.2"}
@ -104,7 +101,28 @@
listora/again {:mvn/version "1.0.0"}
org.clojure/tools.gitlibs {:mvn/version "2.4.172"}
environ/environ {:mvn/version "1.2.0"}
table/table {:git/url "https://github.com/cldwalker/table", :sha "55aef3d5fced682942af811bf5d642f79fb87688"}}
table/table {:git/url "https://github.com/cldwalker/table", :sha "f6293c5f3dac1dd6f525a80fc80930f8ccdf16b7"}
markdown-clj/markdown-clj {:mvn/version "1.10.8"}
org.clojure/tools.namespace {:git/url "https://github.com/babashka/tools.namespace", :sha "a13b037215e21a2e71aa34b27e1dd52c801a2a7b"}
medley/medley {:mvn/version "1.3.0"}
io.github.cognitect-labs/test-runner {:git/tag "v0.5.0", :git/sha "b3fd0d2"}
borkdude/missing.test.assertions {:git/url "https://github.com/borkdude/missing.test.assertions", :sha "603cb01bee72fb17addacc53c34c85612684ad70"}
dev.nubank/docopt {:mvn/version "0.6.1-fix7"}
testdoc/testdoc {:mvn/version "1.4.1"}
org.clojars.lispyclouds/contajners {:mvn/version "0.0.4"}
borkdude/rewrite-edn {:mvn/version "0.1.0"}
clojure-term-colors/clojure-term-colors {:mvn/version "0.1.0"}
io.aviso/pretty {:mvn/version "1.1.1"}
progrock/progrock {:mvn/version "0.1.2"}
djblue/portal {:mvn/version "0.19.0"}
com.wsscode/cljc-misc {:mvn/version "2021.10.16"}
edn-query-language/eql {:mvn/version "2021.07.18"}
meta-merge/meta-merge {:mvn/version "1.0.0"}
com.exoscale/lingo {:mvn/version "1.0.0-alpha14"}
io.github.swirrl/dogstatsd {:mvn/version "0.1.39"}
org.clojure/algo.monads {:mvn/version "0.1.6"}
io.lambdaforge/datalog-parser {:mvn/version "0.1.9"}
clj-stacktrace/clj-stacktrace {:mvn/version "0.2.8"}}
:classpath-overrides {org.clojure/clojure nil
org.clojure/spec.alpha nil}}
:clj-nvd

View file

@ -3,24 +3,24 @@
## Prerequisites
- Install [lein](https://leiningen.org/) for producing uberjars
- Download [GraalVM](https://www.graalvm.org/downloads/). Currently we use *java11-21.3.0*.
- Download [GraalVM](https://www.graalvm.org/downloads/). Currently we use *java11-22.0.0.2*.
- For Windows, installing Visual Studio 2019 with the "Desktop development
with C++" workload is recommended.
- Set `$GRAALVM_HOME` to the GraalVM distribution directory. On macOS this can look like:
``` shell
export GRAALVM_HOME=~/Downloads/graalvm-ce-java11-21.3.0/Contents/Home
export GRAALVM_HOME=~/Downloads/graalvm-ce-java11-22.0.0.2/Contents/Home
```
On linux:
``` shell
export GRAALVM_HOME=~/Downloads/graalvm-ce-java11-21.3.0
export GRAALVM_HOME=~/Downloads/graalvm-ce-java11-22.0.0.2
```
On Windows, from the [Visual Studio 2019 x64 Native Tools Command Prompt](https://github.com/oracle/graal/issues/2116#issuecomment-590470806) or `cmd.exe` (not Powershell):
```
set GRAALVM_HOME=%USERPROFILE%\Downloads\graalvm-ce-java11-21.3.0
set GRAALVM_HOME=%USERPROFILE%\Downloads\graalvm-ce-java11-22.0.0.2
```
If you are not running from the x64 Native Tools Command Prompt, you will need to set additional environment variables using:
```

View file

@ -26,10 +26,22 @@ Sponsoring via [Cognitect](https://www.cognitect.com/).
<img src="https://cdn.nextjournal.com/images/nextjournal-logo.svg" width="300">
### [ATA](https://ata-llc.com) - [hiring](https://www.ziprecruiter.com/c/ATA-LLC/Jobs)
<img width="250" alt="Screen Shot 2022-01-07 at 21 21 00" src="https://user-images.githubusercontent.com/284934/148602984-6c333501-505b-4692-ad7a-62383510fb9a.png">
### [Cognician](https://www.cognician.com)
<img src="https://avatars.githubusercontent.com/u/1450774?s=150&v=4">
### [Fluent](https://fluent.to)
<img src="https://uploads-ssl.webflow.com/600fdbbcf0cbfe02f1a48030/600fdf0fffe881c3e8e298f4_Fluent%20logotype-p-500.png" width="300">
### [180seg](https://www.180s.com.br)
<img src="https://avatars.githubusercontent.com/u/75583439?s=200&v=4">
### [Dr. Evidence](https://www.drevidence.com/)
<img src="https://user-images.githubusercontent.com/284934/138914250-f447ca3d-c1c1-4c60-bfaf-9000541d4a0d.png" width="325">

View file

@ -37,7 +37,7 @@ reasons:
## Requirements
You need [lein](https://leiningen.org/) for running JVM tests and/or producing uberjars. For building binaries you need GraalVM. Currently we use java11-21.3.0.
You need [lein](https://leiningen.org/) for running JVM tests and/or producing uberjars. For building binaries you need GraalVM. Currently we use java11-22.0.0.2.
## Clone repository
@ -81,19 +81,29 @@ Test the native version:
## Tests for Libraries
Babashka runs tests of libraries that are compatible with it through
`script/run_lib_tests`. To add tests for a new library that has a git repository
and run them, use the script `add-libtest.clj` e.g. `script/add-libtest.clj
'{listora/again {:mvn/version "1.0.0"}}' https://github.com/liwp/again --test`.
`script/run_lib_tests`. The script `add-libtest.clj` makes adding new libraries
fairly easy. Some examples:
If the library you want to add doesn't work with the script, you can manually do the following:
```sh
# To add tests for a new library on clojars
script/add-libtest.clj com.exoscale/lingo -t
# To add tests for a new library that is git based only
script/add-libtest.clj '{borkdude/carve {:git/url "https://github.com/borkdude/carve" :sha "df552797a198b6701fb2d92390fce7c59205ea77"}}' -t
# There are a number of options for specifying how to copy tests
script/add-libtest.clj -h
```
If the library you want to add doesn't work automatically, you can manually do the following:
* Add an entry for the library in `deps.edn` under the `:lib-tests` alias.
* Create a directory for the library in `test-resources/lib_tests/` and copy its tests to there.
* Add an entry in `run_all_libtests.clj` to run the added test namespaces.
* Add a manual lib entry using `add-libtest.clj` e.g. `script/add-libtest.clj http-kit/http-kit -m '{:test-namespaces [httpkit.client-test]}'`.
* Run the tests `script/lib_tests/run_all_libtests NS1 NS2`
Note: If you have to modify a test to have it work with bb, add an inline
comment with prefix "BB-TEST-PATCH:" explaining what you did.
Note: If you have to modify any test file or configuration to have it work with
bb, add an inline comment with prefix `BB-TEST-PATCH:` explaining what you did.
## Build
@ -149,7 +159,7 @@ Some of these design decisions were formed in [these discussions](https://github
- Tasks do not allow passing arguments to dependent tasks, other than by rebinding `*command-line-args*` (see discussion).
- Does the list of dependencies need to be dynamic? No, see discussion (same reason as args)
- bb <foo> is resolved as file > task > bb subcommand. Shadowing future subcommand is a problem that a user can solve by renaming a task or file. (same as lein aliases). Also see Conflicts.
- bb &lt;foo&gt; is resolved as file > task > bb subcommand. Shadowing future subcommand is a problem that a user can solve by renaming a task or file. (same as lein aliases). Also see Conflicts.
- It is a feature that tasks are defined as top-level vars (instead of local let-bound symbols). This plays well with the Gilardi scenario, e.g. here: https://github.com/babashka/babashka.github.io/blob/ad276625f6c41f269d19450f236cb54cab2591e1/bb.edn#L7.
- The parallel option trickles down into run calls. People who use parallel will be confused if its dropped magically, people who dont use parallel wont notice anything either way so it doesnt matter

81
doc/libraries.csv Normal file
View file

@ -0,0 +1,81 @@
maven-name,git-url
aero/aero,http://github.com/juxt/aero
amperity/vault-clj,https://github.com/amperity/vault-clj
babashka/babashka.curl,https://github.com/babashka/babashka.curl
better-cond/better-cond,https://github.com/Engelberg/better-cond
borkdude/deps,https://github.com/borkdude/deps.clj
borkdude/missing.test.assertions,https://github.com/borkdude/missing.test.assertions
borkdude/rewrite-edn,https://github.com/borkdude/rewrite-edn
camel-snake-kebab/camel-snake-kebab,https://github.com/clj-commons/camel-snake-kebab
circleci/bond,https://github.com/circleci/bond
clj-commons/clj-yaml,https://github.com/clj-commons/clj-yaml
clj-commons/multigrep,https://github.com/clj-commons/multigrep
clj-stacktrace/clj-stacktrace,https://github.com/mmcgrana/clj-stacktrace
clojure-csv/clojure-csv,https://github.com/davidsantiago/clojure-csv
clojure-term-colors/clojure-term-colors,https://github.com/trhura/clojure-term-colors
com.exoscale/lingo,https://github.com/exoscale/lingo
com.github.seancorfield/honeysql,https://github.com/seancorfield/honeysql
com.grammarly/omniconf,https://github.com/grammarly/omniconf
com.stuartsierra/component,https://github.com/stuartsierra/component
com.stuartsierra/dependency,https://github.com/stuartsierra/dependency
com.wsscode/cljc-misc,https://github.com/wilkerlucio/cljc-misc
comb/comb,https://github.com/weavejester/comb
cprop/cprop,https://github.com/tolitius/cprop
crispin/crispin,https://github.com/dunaj-project/crispin
dev.nubank/docopt,https://github.com/nubank/docopt.clj
djblue/portal,https://github.com/djblue/portal
doric/doric,https://github.com/joegallo/doric
douglass/clj-psql,https://github.com/DarinDouglass/clj-psql
edn-query-language/eql,https://github.com/edn-query-language/eql
environ/environ,https://github.com/weavejester/environ
exoscale/coax,https://github.com/exoscale/coax
expound/expound,https://github.com/bhb/expound
failjure/failjure,https://github.com/adambard/failjure
ffclj/ffclj,https://github.com/luissantos/ffclj
gaka/gaka,https://github.com/cdaddr/gaka
hato/hato,https://github.com/gnarroway/hato
henryw374/cljc.java-time,https://github.com/henryw374/cljc.java-time
hiccup/hiccup,http://github.com/weavejester/hiccup
honeysql/honeysql,https://github.com/seancorfield/honeysql
http-kit/http-kit,https://github.com/http-kit/http-kit
integrant/integrant,https://github.com/weavejester/integrant
io.aviso/pretty,https://github.com/AvisoNovate/pretty
io.github.cognitect-labs/test-runner,https://github.com/cognitect-labs/test-runner
io.github.swirrl/dogstatsd,https://github.com/swirrl/dogstatsd
io.github.technomancy/limit-break,https://github.com/technomancy/limit-break
io.helins/binf,https://github.com/helins/binf.cljc
io.lambdaforge/datalog-parser,https://github.com/lambdaforge/datalog-parser
io.replikativ/hasch,https://github.com/replikativ/hasch
java-http-clj/java-http-clj,http://www.github.com/schmee/java-http-clj
lambdaisland/regal,https://github.com/lambdaisland/regal
listora/again,https://github.com/liwp/again
markdown-clj/markdown-clj,https://github.com/yogthos/markdown-clj
medley/medley,https://github.com/weavejester/medley
meta-merge/meta-merge,https://github.com/weavejester/meta-merge
minimallist/minimallist,https://github.com/green-coder/minimallist
mvxcvi/arrangement,https://github.com/greglook/clj-arrangement
orchestra/orchestra,https://github.com/jeaye/orchestra
org.babashka/spec.alpha,https://github.com/babashka/spec.alpha
org.clj-commons/clj-http-lite,https://github.com/clj-commons/clj-http-lite
org.clj-commons/digest,https://github.com/clj-commons/clj-digest
org.clojars.askonomm/ruuter,https://github.com/askonomm/ruuter
org.clojars.lispyclouds/contajners,https://github.com/lispyclouds/contajners
org.clojure/algo.monads,https://github.com/clojure/algo.monads
org.clojure/core.match,https://github.com/clojure/core.match
org.clojure/data.csv,https://github.com/clojure/data.csv
org.clojure/data.generators,https://github.com/clojure/data.generators
org.clojure/data.json,https://github.com/clojure/data.json
org.clojure/data.zip,https://github.com/clojure/data.zip
org.clojure/math.combinatorics,https://github.com/clojure/math.combinatorics
org.clojure/test.check,https://github.com/clojure/test.check
org.clojure/tools.gitlibs,https://github.com/clojure/tools.gitlibs
org.clojure/tools.namespace,https://github.com/babashka/tools.namespace
progrock/progrock,https://github.com/weavejester/progrock
reifyhealth/specmonstah,https://github.com/reifyhealth/specmonstah
rewrite-clj/rewrite-clj,https://github.com/clj-commons/rewrite-clj
rm-hull/jasentaa,https://github.com/rm-hull/jasentaa
selmer/selmer,https://github.com/yogthos/Selmer
slingshot/slingshot,https://github.com/scgilardi/slingshot
table/table,https://github.com/cldwalker/table
testdoc/testdoc,https://github.com/liquidz/testdoc
version-clj/version-clj,https://github.com/xsc/version-clj
1 maven-name git-url
2 aero/aero http://github.com/juxt/aero
3 amperity/vault-clj https://github.com/amperity/vault-clj
4 babashka/babashka.curl https://github.com/babashka/babashka.curl
5 better-cond/better-cond https://github.com/Engelberg/better-cond
6 borkdude/deps https://github.com/borkdude/deps.clj
7 borkdude/missing.test.assertions https://github.com/borkdude/missing.test.assertions
8 borkdude/rewrite-edn https://github.com/borkdude/rewrite-edn
9 camel-snake-kebab/camel-snake-kebab https://github.com/clj-commons/camel-snake-kebab
10 circleci/bond https://github.com/circleci/bond
11 clj-commons/clj-yaml https://github.com/clj-commons/clj-yaml
12 clj-commons/multigrep https://github.com/clj-commons/multigrep
13 clj-stacktrace/clj-stacktrace https://github.com/mmcgrana/clj-stacktrace
14 clojure-csv/clojure-csv https://github.com/davidsantiago/clojure-csv
15 clojure-term-colors/clojure-term-colors https://github.com/trhura/clojure-term-colors
16 com.exoscale/lingo https://github.com/exoscale/lingo
17 com.github.seancorfield/honeysql https://github.com/seancorfield/honeysql
18 com.grammarly/omniconf https://github.com/grammarly/omniconf
19 com.stuartsierra/component https://github.com/stuartsierra/component
20 com.stuartsierra/dependency https://github.com/stuartsierra/dependency
21 com.wsscode/cljc-misc https://github.com/wilkerlucio/cljc-misc
22 comb/comb https://github.com/weavejester/comb
23 cprop/cprop https://github.com/tolitius/cprop
24 crispin/crispin https://github.com/dunaj-project/crispin
25 dev.nubank/docopt https://github.com/nubank/docopt.clj
26 djblue/portal https://github.com/djblue/portal
27 doric/doric https://github.com/joegallo/doric
28 douglass/clj-psql https://github.com/DarinDouglass/clj-psql
29 edn-query-language/eql https://github.com/edn-query-language/eql
30 environ/environ https://github.com/weavejester/environ
31 exoscale/coax https://github.com/exoscale/coax
32 expound/expound https://github.com/bhb/expound
33 failjure/failjure https://github.com/adambard/failjure
34 ffclj/ffclj https://github.com/luissantos/ffclj
35 gaka/gaka https://github.com/cdaddr/gaka
36 hato/hato https://github.com/gnarroway/hato
37 henryw374/cljc.java-time https://github.com/henryw374/cljc.java-time
38 hiccup/hiccup http://github.com/weavejester/hiccup
39 honeysql/honeysql https://github.com/seancorfield/honeysql
40 http-kit/http-kit https://github.com/http-kit/http-kit
41 integrant/integrant https://github.com/weavejester/integrant
42 io.aviso/pretty https://github.com/AvisoNovate/pretty
43 io.github.cognitect-labs/test-runner https://github.com/cognitect-labs/test-runner
44 io.github.swirrl/dogstatsd https://github.com/swirrl/dogstatsd
45 io.github.technomancy/limit-break https://github.com/technomancy/limit-break
46 io.helins/binf https://github.com/helins/binf.cljc
47 io.lambdaforge/datalog-parser https://github.com/lambdaforge/datalog-parser
48 io.replikativ/hasch https://github.com/replikativ/hasch
49 java-http-clj/java-http-clj http://www.github.com/schmee/java-http-clj
50 lambdaisland/regal https://github.com/lambdaisland/regal
51 listora/again https://github.com/liwp/again
52 markdown-clj/markdown-clj https://github.com/yogthos/markdown-clj
53 medley/medley https://github.com/weavejester/medley
54 meta-merge/meta-merge https://github.com/weavejester/meta-merge
55 minimallist/minimallist https://github.com/green-coder/minimallist
56 mvxcvi/arrangement https://github.com/greglook/clj-arrangement
57 orchestra/orchestra https://github.com/jeaye/orchestra
58 org.babashka/spec.alpha https://github.com/babashka/spec.alpha
59 org.clj-commons/clj-http-lite https://github.com/clj-commons/clj-http-lite
60 org.clj-commons/digest https://github.com/clj-commons/clj-digest
61 org.clojars.askonomm/ruuter https://github.com/askonomm/ruuter
62 org.clojars.lispyclouds/contajners https://github.com/lispyclouds/contajners
63 org.clojure/algo.monads https://github.com/clojure/algo.monads
64 org.clojure/core.match https://github.com/clojure/core.match
65 org.clojure/data.csv https://github.com/clojure/data.csv
66 org.clojure/data.generators https://github.com/clojure/data.generators
67 org.clojure/data.json https://github.com/clojure/data.json
68 org.clojure/data.zip https://github.com/clojure/data.zip
69 org.clojure/math.combinatorics https://github.com/clojure/math.combinatorics
70 org.clojure/test.check https://github.com/clojure/test.check
71 org.clojure/tools.gitlibs https://github.com/clojure/tools.gitlibs
72 org.clojure/tools.namespace https://github.com/babashka/tools.namespace
73 progrock/progrock https://github.com/weavejester/progrock
74 reifyhealth/specmonstah https://github.com/reifyhealth/specmonstah
75 rewrite-clj/rewrite-clj https://github.com/clj-commons/rewrite-clj
76 rm-hull/jasentaa https://github.com/rm-hull/jasentaa
77 selmer/selmer https://github.com/yogthos/Selmer
78 slingshot/slingshot https://github.com/scgilardi/slingshot
79 table/table https://github.com/cldwalker/table
80 testdoc/testdoc https://github.com/liquidz/testdoc
81 version-clj/version-clj https://github.com/xsc/version-clj

View file

@ -5,6 +5,53 @@ you have anything to add. Also see
[#babashka](https://twitter.com/hashtag/babashka?src=hashtag_click&f=live) on
Twitter.
## 2021-12
- Releases: [0.6.8 - 0.7.3](https://github.com/babashka/babashka/blob/master/CHANGELOG.md).
- [Scripting with Babashka on Alfred](https://blog.wsscode.com/babashka-and-alfred/) by Wilker Lucio
- [babashka/spec.alpha](https://github.com/babashka/spec.alpha): a fork of spec.alpha that works with babashka.
- Several people are doing [Advent of Code puzzles with babashka](https://twitter.com/search?q=%23babashka%20%20%23AdventOfCode&src=typed_query&f=live)
- Compatibility with a [fork of tools.namespace](https://github.com/babashka/tools.namespace). This allows
running the Cognitect [test-runner](https://github.com/cognitect-labs/test-runner) (Cognitest) from source.
- [bb-components](https://github.com/vedang/bb-scripts#bb-components): A script to find all the components that you should deploy your code to.
- [Babashka workshop at JavaLand](https://github.com/ijug-ev/JavaLand/tree/main/Community-Aktivit%C3%A4ten#bash-war-gestern-shell-scripting-mit-babashka-clojure-ug-d%C3%BCsseldorf-christian-meter-rheinjug-jens-bendisposto)
- Install babashka [dev builds](https://twitter.com/borkdude/status/1475234968146227203)
- [Combine babashka and PHP](https://gist.github.com/borkdude/843548cba14ae9d283191e31bc483959)
- [System wide babashka tasks](https://twitter.com/borkdude/status/1476656022282551300)
- [Run an http file server as a babashka task](https://twitter.com/borkdude/status/1476870516233445377)
## 2021-11
- Releases: [0.6.5 - 0.6.7](https://github.com/babashka/babashka/blob/master/CHANGELOG.md).
- [Contajners](https://github.com/lispyclouds/contajners): An idiomatic,
data-driven, REPL friendly clojure client for OCI container engines.
- [deps-modules](https://github.com/exoscale/deps-modules#babashka): a clojure "tool" that attempts to solve one of the "multi module" project problems with tools.deps in a minimalistic way.
- [Moldable Emacs: a Clojure Playground with Babashka](https://ag91.github.io/blog/2021/11/05/moldable-emacs-a-clojure-playground-with-babashka/)
- [aws pod 0.1.0](https://twitter.com/borkdude/status/1459117378441261056)
- [tools.bbuild](https://github.com/babashka/tools.bbuild): a fork of tools.build that runs with babashka and [tools-deps-native](https://github.com/babashka/tools-deps-native)
- [Making markdown-clj babashka compatible](https://blog.michielborkent.nl/markdown-clj-babashka-compatible.html) by Michiel Borkent
- [radiale](https://github.com/xlfe/radiale): radiale: home automation project written using #babashka and Python
- [Writing a Clojure shell script with Babashka](https://www.youtube.com/watch?v=D-_Mz7rz1po), a video by Max Weber
- [makejack](https://github.com/hugoduncan/makejack): A clojure CLI build tool, and build library which can run with babashka.
- [I wrote myself a static site generator](https://freeston.me/posts/2021-11-29-new-site-generator/) (in babashka) by Dominic Freeston.
- [bipe](https://gist.github.com/borkdude/82dcdd36a1e61ef36f19221876e7b1b6): vipe for babashka
## 2021-10
- Releases: [0.6.2-0.6.4](https://github.com/babashka/babashka/blob/master/CHANGELOG.md).
- Babashka on the [Thoughtworks Technology Radar](https://www.thoughtworks.com/radar/platforms/babashka)
- [ruuter](https://github.com/askonomm/ruuter#setting-up-with-babashka) is a
routing library compatible with babashka.
- A list of [companies](https://github.com/babashka/babashka/blob/master/doc/companies.md) using babashka
- Ilshat Sultanov shares his [babashka tasks](https://twitter.com/just_sultanov/status/1446118161258987534)
- [Slack the music](https://github.com/javahippie/slack-the-music), a babashka script to update your slack status with your current Apple Music track by Tim Zöller.
- [Finding my inner Wes Anderson](https://javahippie.net/clojure/2021/10/18/finding-my-inner-wes-anderson.html) by Tim Zöller.
- [Run a local babashka script in a remote server](https://twitter.com/borkdude/status/1451110414062870528)
- [Replacing my Octopress blog with 200 lines of Babashka](https://blog.michielborkent.nl/migrating-octopress-to-babashka.html) by Michiel Borkent
- The babashka wiki now has a [GNU Emacs](https://github.com/babashka/babashka/wiki/GNU-Emacs) section
- Invoke babashka tasks in a [monorepo](https://github.com/babashka/babashka/discussions/1044#discussioncomment-1544956)
- [Speeding up builds with fs/modified-since](https://blog.michielborkent.nl/speeding-up-builds-fs-modified-since.html) by Michiel Borkent
## 2021-09
- New babashka 0.6.0 released. Highlight: support for `java.net.http` which
@ -13,6 +60,13 @@ Twitter.
http related scripting towards `java.net.http` in favor of the other two
solutions currently available in `bb`: `babashka.curl` and
`org.httpkit.client`.
- [rss-saver](https://github.com/adam-james-v/rss-saver): Simple Clojure (Babashka) script that saves articles from world.hey.com RSS feeds.
- [babashka-docker-action-example](https://github.com/borkdude/babashka-docker-action-example)
- [script](https://gist.github.com/rutenkolk/dbd970d03a0d012b671db38434ccbfa7) to upgrade zig lang to the latest dev release
- [Cursive](https://twitter.com/CursiveIDE/status/1439022267187433472) adds support for babashka in 1.11.0
- How to filter tail output with babashka on [StackOverflow](https://stackoverflow.com/questions/69241046/how-to-filter-output-of-tail-with-babashka/69241911?stw=2#69241911)
- [Awesome Babashka: Parse & produce HTML and SQLite](https://blog.jakubholy.net/2021/awesome-babashka-dash/) by Jakub Holy
- [neil](https://github.com/babashka/neil): an installable babashka script to add common aliases and features to deps.edn-based projects.
## 2021-08

View file

@ -2,93 +2,98 @@
The following libraries and projects are known to work with babashka.
- [Libraries](#libraries)
- [tools.namespace](#toolsnamespace)
- [test-runner](#test-runner)
- [spec.alpha](#specalpha)
- [tools.bbuild](#toolsbbuild)
- [clj-http-lite](#clj-http-lite)
- [spartan.spec](#spartanspec)
- [missing.test.assertions](#missingtestassertions)
- [medley](#medley)
- [limit-break](#limit-break)
- [clojure-csv](#clojure-csv)
- [regal](#regal)
- [cprop](#cprop)
- [comb](#comb)
- [nubank/docopt](#nubankdocopt)
- [arrangement](#arrangement)
- [clojure.math.combinatorics](#clojuremathcombinatorics)
- [testdoc](#testdoc)
- [doric](#doric)
- [clojure.data.zip](#clojuredatazip)
- [clj-psql](#clj-psql)
- [camel-snake-kebab](#camel-snake-kebab)
- [aero](#aero)
- [clojure.data.generators](#clojuredatagenerators)
- [honeysql](#honeysql)
- [bond](#bond)
- [portal](#portal)
- [version-clj](#version-clj)
- [matchete](#matchete)
- [progrock](#progrock)
- [clj-commons/fs](#clj-commonsfs)
- [cljc.java-time](#cljcjava-time)
- [environ](#environ)
- [gaka](#gaka)
- [failjure](#failjure)
- [pretty](#pretty)
- [clojure-term-colors](#clojure-term-colors)
- [binf](#binf)
- [rewrite-edn](#rewrite-edn)
- [expound](#expound)
- [omniconf](#omniconf)
- [slingshot](#slingshot)
- [hasch](#hasch)
- [crispin](#crispin)
- [ffclj](#ffclj)
- [multigrep](#multigrep)
- [java-http-clj](#java-http-clj)
- [component](#component)
- [minimallist](#minimallist)
- [ruuter](#ruuter)
- [clj-commons.digest](#clj-commonsdigest)
- [contajners](#contajners)
- [dependency](#dependency)
- [specmonstah](#specmonstah)
- [Pods](#pods)
- [Projects](#projects-1)
- [babashka-test-action](#babashka-test-action)
- [deps.clj](#depsclj)
- [4bb](#4bb)
- [babashka lambda layer](#babashka-lambda-layer)
- [Release on push Github action](#release-on-push-github-action)
- [justone/bb-scripts](#justonebb-scripts)
- [nativity](#nativity)
- [cldwalker/bb-clis](#cldwalkerbb-clis)
- [krell template](#krell-template)
- [wee-httpd](#wee-httpd)
- [covid19-babashka](#covid19-babashka)
- [bb-spotify](#bb-spotify)
- [lambdaisland/open-source](#lambdaislandopen-source)
- [dharrigan/spotifyd-notification](#dharriganspotifyd-notification)
- [nextjournal/ssh-github-auth](#nextjournalssh-github-auth)
- [turtlequeue/setup-babashka](#turtlequeuesetup-babashka)
- [interdep](#interdep)
- [sha-words](#sha-words)
- [adam-james-v/scripts](#adam-james-vscripts)
- [oidc-client](#oidc-client)
- [jirazzz](#jirazzz)
- [Babashka + scittle guestbook](#babashka--scittle-guestbook)
- [bb htmx todo app](#bb-htmx-todo-app)
- [Projects](#projects)
- [Libraries](#libraries)
- [tools.namespace](#toolsnamespace)
- [test-runner](#test-runner)
- [spec.alpha](#specalpha)
- [tools.bbuild](#toolsbbuild)
- [clj-http-lite](#clj-http-lite)
- [spartan.spec](#spartanspec)
- [missing.test.assertions](#missingtestassertions)
- [medley](#medley)
- [limit-break](#limit-break)
- [clojure-csv](#clojure-csv)
- [regal](#regal)
- [cprop](#cprop)
- [comb](#comb)
- [nubank/docopt](#nubankdocopt)
- [arrangement](#arrangement)
- [clojure.math.combinatorics](#clojuremathcombinatorics)
- [testdoc](#testdoc)
- [doric](#doric)
- [clojure.data.zip](#clojuredatazip)
- [clj-psql](#clj-psql)
- [camel-snake-kebab](#camel-snake-kebab)
- [aero](#aero)
- [clojure.data.generators](#clojuredatagenerators)
- [honeysql](#honeysql)
- [bond](#bond)
- [portal](#portal)
- [version-clj](#version-clj)
- [matchete](#matchete)
- [progrock](#progrock)
- [clj-commons/fs](#clj-commonsfs)
- [cljc.java-time](#cljcjava-time)
- [environ](#environ)
- [gaka](#gaka)
- [failjure](#failjure)
- [pretty](#pretty)
- [clojure-term-colors](#clojure-term-colors)
- [binf](#binf)
- [rewrite-edn](#rewrite-edn)
- [expound](#expound)
- [omniconf](#omniconf)
- [slingshot](#slingshot)
- [hasch](#hasch)
- [crispin](#crispin)
- [ffclj](#ffclj)
- [multigrep](#multigrep)
- [java-http-clj](#java-http-clj)
- [component](#component)
- [minimallist](#minimallist)
- [ruuter](#ruuter)
- [clj-commons.digest](#clj-commonsdigest)
- [contajners](#contajners)
- [dependency](#dependency)
- [specmonstah](#specmonstah)
- [markdown-clj](#markdown-clj)
- [algo.monads](#algomonads)
- [Pods](#pods)
- [Projects](#projects-1)
- [babashka-test-action](#babashka-test-action)
- [deps.clj](#depsclj)
- [4bb](#4bb)
- [babashka lambda layer](#babashka-lambda-layer)
- [Release on push Github action](#release-on-push-github-action)
- [justone/bb-scripts](#justonebb-scripts)
- [nativity](#nativity)
- [cldwalker/bb-clis](#cldwalkerbb-clis)
- [krell template](#krell-template)
- [wee-httpd](#wee-httpd)
- [covid19-babashka](#covid19-babashka)
- [bb-spotify](#bb-spotify)
- [lambdaisland/open-source](#lambdaislandopen-source)
- [dharrigan/spotifyd-notification](#dharriganspotifyd-notification)
- [nextjournal/ssh-github-auth](#nextjournalssh-github-auth)
- [turtlequeue/setup-babashka](#turtlequeuesetup-babashka)
- [interdep](#interdep)
- [sha-words](#sha-words)
- [adam-james-v/scripts](#adam-james-vscripts)
- [oidc-client](#oidc-client)
- [jirazzz](#jirazzz)
- [Babashka + scittle guestbook](#babashka--scittle-guestbook)
- [bb htmx todo app](#bb-htmx-todo-app)
- [bb aws lambda runtime](#bb-aws-lambda-runtime)
For more supported libraries, see [this test
file](../test-resources/lib_tests/babashka/run_all_libtests.clj ). Also keep an eye
on the [news](news.md) page for new projects, gists and other developments
around babashka.
Also keep an eye on the [news](news.md) page for new projects, gists and other
developments around babashka.
## Libraries
For a full list of libraries, see [libraries.csv](./libraries.csv). To add a
library, see [these instructions](./dev.md#tests-for-libraries).
### [tools.namespace](https://github.com/babashka/tools.namespace)
A fork of `tools.namespace`. This is used by other libraries and enables them to
@ -110,12 +115,12 @@ instrumentation! Its readme also contains instructions on how to use
A fork of `tools.build`.
### [clj-http-lite](https://github.com/babashka/clj-http-lite)
### [clj-http-lite](https://github.com/clj-commons/clj-http-lite)
A fork of a fork of `clj-http-lite`. Example:
Example:
``` shell
$ export BABASHKA_CLASSPATH="$(clojure -Sdeps '{:deps {clj-http-lite {:git/url "https://github.com/babashka/clj-http-lite" :sha "f44ebe45446f0f44f2b73761d102af3da6d0a13e"}}}' -Spath)"
$ export BABASHKA_CLASSPATH="$(clojure -Sdeps '{:deps {org.clj-commons/clj-http-lite {:mvn/version "0.4.392"}}}' -Spath)"
$ bb "(require '[clj-http.lite.client :as client]) (:status (client/get \"https://www.clojure.org\"))"
200
@ -145,16 +150,10 @@ Ran 1 tests containing 0 assertions.
### [medley](https://github.com/weavejester/medley/)
Requires `bb` >= v0.0.71. Latest coordinates checked with with bb:
``` clojure
{:git/url "https://github.com/weavejester/medley" :sha "a4e5fb5383f5c0d83cb2d005181a35b76d8a136d"}
```
Example:
``` shell
$ export BABASHKA_CLASSPATH=$(clojure -Spath -Sdeps '{:deps {medley {:git/url "https://github.com/weavejester/medley" :sha "a4e5fb5383f5c0d83cb2d005181a35b76d8a136d"}}}')
$ export BABASHKA_CLASSPATH=$(clojure -Spath -Sdeps '{:deps {medley/medley {:mvn/version "1.3.0"}}}')
$ bb -e "(require '[medley.core :as m]) (m/index-by :id [{:id 1} {:id 2}])"
{1 {:id 1}, 2 {:id 2}}
@ -201,16 +200,10 @@ export BABASHKA_CLASSPATH="$(clojure -Sdeps '{:deps {clojure-csv {:mvn/version "
### [regal](https://github.com/lambdaisland/regal)
Requires `bb` >= v0.0.71. Latest coordinates checked with with bb:
``` clojure
{:git/url "https://github.com/lambdaisland/regal" :sha "d4e25e186f7b9705ebb3df6b21c90714d278efb7"}
```
Example:
``` shell
$ export BABASHKA_CLASSPATH=$(clojure -Spath -Sdeps '{:deps {regal {:git/url "https://github.com/lambdaisland/regal" :sha "d4e25e186f7b9705ebb3df6b21c90714d278efb7"}}}')
$ export BABASHKA_CLASSPATH=$(clojure -Spath -Sdeps '{:deps {lambdaisland/regal {:mvn/version "0.0.143"}}}')
$ bb -e "(require '[lambdaisland.regal :as regal]) (regal/regex [:* \"ab\"])"
#"(?:\Qab\E)*"
@ -792,6 +785,14 @@ Represent dependency graphs as a directed acylic graph.
Write concise, maintainable test fixtures with clojure.spec.alpha.
### [markdown-clj](https://github.com/yogthos/markdown-clj)
Markdown parser that translates markdown to html.
### [algo.monads](https://github.com/clojure/algo.monads)
Macros for defining monads, and definition of the most common monads.
## Pods
[Babashka pods](https://github.com/babashka/babashka.pods) are programs that can

View file

@ -549,3 +549,9 @@ $ bb db_who.clj
| fred@192.168.1.2 | workbench |
| jane@192.168.1.3 | Toad for mySQL |
```
## Single page application with Babashka + htmx
Example of a todo list SPA using Babashka and htmx
See [htmx_todoapp.clj](htmx_todoapp.clj)
Contributed by [@prestancedesign](https://github.com/prestancedesign).

240
examples/htmx_todoapp.clj Normal file
View file

@ -0,0 +1,240 @@
#!/usr/bin/env bb
;; Source: https://github.com/prestancedesign/babashka-htmx-todoapp
(require '[org.httpkit.server :as srv]
'[clojure.java.browse :as browse]
'[clojure.core.match :refer [match]]
'[clojure.pprint :refer [cl-format]]
'[clojure.string :as str]
'[hiccup.core :as h])
(import '[java.net URLDecoder])
;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Config
;;;;;;;;;;;;;;;;;;;;;;;;;;
(def port 3000)
;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Mimic DB (in-memory)
;;;;;;;;;;;;;;;;;;;;;;;;;;
(def todos (atom (sorted-map 1 {:id 1 :name "Taste htmx with Babashka" :done true}
2 {:id 2 :name "Buy a unicorn" :done false})))
(def todos-id (atom (count @todos)))
;;;;;;;;;;;;;;;;;;;;;;;;;;
;; "DB" queries
;;;;;;;;;;;;;;;;;;;;;;;;;;
(defn add-todo! [name]
(let [id (swap! todos-id inc)]
(swap! todos assoc id {:id id :name name :done false})))
(defn toggle-todo! [id]
(swap! todos update-in [(Integer. id) :done] not))
(defn remove-todo! [id]
(swap! todos dissoc (Integer. id)))
(defn filtered-todo [filter-name todos]
(case filter-name
"active" (remove #(:done (val %)) todos)
"completed" (filter #(:done (val %)) todos)
"all" todos
todos))
(defn get-items-left []
(count (remove #(:done (val %)) @todos)))
(defn todos-completed []
(count (filter #(:done (val %)) @todos)))
(defn remove-all-completed-todo []
(reset! todos (into {} (remove #(:done (val %)) @todos))))
;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Template and components
;;;;;;;;;;;;;;;;;;;;;;;;;;
(defn todo-item [{:keys [id name done]}]
[:li {:id (str "todo-" id)
:class (when done "completed")}
[:div.view
[:input.toggle {:hx-patch (str "/todos/" id)
:type "checkbox"
:checked done
:hx-target (str "#todo-" id)
:hx-swap "outerHTML"}]
[:label {:hx-get (str "/todos/edit/" id)
:hx-target (str "#todo-" id)
:hx-swap "outerHTML"} name]
[:button.destroy {:hx-delete (str "/todos/" id)
:_ (str "on htmx:afterOnLoad remove #todo-" id)}]]])
(defn todo-list [todos]
(for [todo todos]
(todo-item (val todo))))
(defn todo-edit [id name]
[:form {:hx-post (str "/todos/update/" id)}
[:input.edit {:type "text"
:name "name"
:value name}]])
(defn item-count []
(let [items-left (get-items-left)]
[:span#todo-count.todo-count {:hx-swap-oob "true"}
[:strong items-left] (cl-format nil " item~p " items-left) "left"]))
(defn todo-filters [filter]
[:ul#filters.filters {:hx-swap-oob "true"}
[:li [:a {:hx-get "/?filter=all"
:hx-push-url "true"
:hx-target "#todo-list"
:class (when (= filter "all") "selected")} "All"]]
[:li [:a {:hx-get "/?filter=active"
:hx-push-url "true"
:hx-target "#todo-list"
:class (when (= filter "active") "selected")} "Active"]]
[:li [:a {:hx-get "/?filter=completed"
:hx-push-url "true"
:hx-target "#todo-list"
:class (when (= filter "completed") "selected")} "Completed"]]])
(defn clear-completed-button []
[:button#clear-completed.clear-completed
{:hx-delete "/todos"
:hx-target "#todo-list"
:hx-swap-oob "true"
:hx-push-url "/"
:class (when-not (pos? (todos-completed)) "hidden")}
"Clear completed"])
(defn template [filter]
(str
"<!DOCTYPE html>"
(h/html
[:head
[:meta {:charset "UTF-8"}]
[:title "Htmx + Babashka"]
[:link {:href "https://unpkg.com/todomvc-app-css@2.4.1/index.css" :rel "stylesheet"}]
[:script {:src "https://unpkg.com/htmx.org@1.5.0/dist/htmx.min.js" :defer true}]
[:script {:src "https://unpkg.com/hyperscript.org@0.8.1/dist/_hyperscript.min.js" :defer true}]]
[:body
[:section.todoapp
[:header.header
[:h1 "todos"]
[:form
{:hx-post "/todos"
:hx-target "#todo-list"
:hx-swap "beforeend"
:_ "on htmx:afterOnLoad set #txtTodo.value to ''"}
[:input#txtTodo.new-todo
{:name "todo"
:placeholder "What needs to be done?"
:autofocus ""}]]]
[:section.main
[:input#toggle-all.toggle-all {:type "checkbox"}]
[:label {:for "toggle-all"} "Mark all as complete"]]
[:ul#todo-list.todo-list
(todo-list (filtered-todo filter @todos))]
[:footer.footer
(item-count)
(todo-filters filter)
(clear-completed-button)]]
[:footer.info
[:p "Click to edit a todo"]
[:p "Created by "
[:a {:href "https://twitter.com/PrestanceDesign"} "Michaël Sλlihi"]]
[:p "Part of "
[:a {:href "http://todomvc.com"} "TodoMVC"]]]])))
;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Helpers
;;;;;;;;;;;;;;;;;;;;;;;;;;
(defn parse-body [body]
(-> body
slurp
(str/split #"=")
second
URLDecoder/decode))
(defn parse-query-string [query-string]
(when query-string
(-> query-string
(str/split #"=")
second)))
;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Handlers
;;;;;;;;;;;;;;;;;;;;;;;;;;
(defn app-index [{:keys [query-string headers]}]
(let [filter (parse-query-string query-string)
ajax-request? (get headers "hx-request")]
(if (and filter ajax-request?)
(h/html (todo-list (filtered-todo filter @todos))
(todo-filters filter))
(template filter))))
(defn add-item [{body :body}]
(let [name (parse-body body)
todo (add-todo! name)]
(h/html (todo-item (val (last todo)))
(item-count))))
(defn edit-item [id]
(let [{:keys [id name]} (get @todos (Integer. id))]
(h/html (todo-edit id name))))
(defn update-item [{body :body} id]
(let [name (parse-body body)
todo (swap! todos assoc-in [(Integer. id) :name] name)]
(h/html (todo-item (get todo (Integer. id))))))
(defn patch-item [id]
(let [todo (toggle-todo! id)]
(h/html (todo-item (get todo (Integer. id)))
(item-count)
(clear-completed-button))))
(defn delete-item [id]
(remove-todo! id)
(h/html (item-count)))
(defn clear-completed []
(remove-all-completed-todo)
(h/html (todo-list @todos)
(item-count)
(clear-completed-button)))
;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Routes
;;;;;;;;;;;;;;;;;;;;;;;;;;
(defn routes [{:keys [request-method uri] :as req}]
(let [path (vec (rest (str/split uri #"/")))]
(match [request-method path]
[:get []] {:body (app-index req)}
[:get ["todos" "edit" id]] {:body (edit-item id)}
[:post ["todos"]] {:body (add-item req)}
[:post ["todos" "update" id]] {:body (update-item req id)}
[:patch ["todos" id]] {:body (patch-item id)}
[:delete ["todos" id]] {:body (delete-item id)}
[:delete ["todos"]] {:body (clear-completed)}
:else {:status 404 :body "Error 404: Page not found"})))
;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Server
;;;;;;;;;;;;;;;;;;;;;;;;;;
(when (= *file* (System/getProperty "babashka.file"))
(let [url (str "http://localhost:" port "/")]
(srv/run-server #'routes {:port port})
(println "serving" url)
(browse/browse-url url)
@(promise)))

View file

@ -2,7 +2,7 @@
#_" -*- mode: clojure; -*-"
;; Source: https://gist.github.com/holyjak/36c6284c047ffb7573e8a34399de27d8
;; Based on https://github.com/babashka/babashka/blob/master/examples/image_viewer.clj
;; Based on https://github.com/babashka/babashka/blob/master/examples/image-viewer.clj
(ns http-server
(:require [babashka.fs :as fs]
[clojure.java.browse :as browse]

2
fs

@ -1 +1 @@
Subproject commit 6019ec9cb09632fdf84e4bc5879fd47ed57a35eb
Subproject commit a151ca0ef45dd4126a26d82737cc2c4434f38e71

11
install
View file

@ -88,7 +88,7 @@ case "$(uname -m)" in
esac
# Ugly ugly conversion of version to a comparable number
IFS='.' read -ra VER <<< "$version"
IFS='.' read -ra VER <<< "${version//-SNAPSHOT/}"
vernum=$(printf "%03d%03d%03d" "${VER[0]}" "${VER[1]}" "${VER[2]}")
if [[ 10#$vernum -le 10#000002013 ]]; then
@ -109,7 +109,14 @@ case "$platform-$static_binary" in
;;
esac
download_url="https://github.com/babashka/babashka/releases/download/v$version/$filename"
if [[ "$version" == *-SNAPSHOT ]]
then
repo="babashka-dev-builds"
else
repo="babashka"
fi
download_url="https://github.com/babashka/$repo/releases/download/v$version/$filename"
# macOS only have shasum available by default
# Some Linux distros (RHEL-like) only have sha256sum avaiable by default (others have both)

@ -1 +1 @@
Subproject commit cc298e4a75e307f1265dcce11c629ea088423a9e
Subproject commit 927935a9684804692a745f038ec75c56a867c6fb

View file

@ -17,17 +17,19 @@
:resource-paths ["resources" "sci/resources"]
:test-selectors {:default (complement :windows-only)
:windows (complement :skip-windows)}
:dependencies [[org.clojure/clojure "1.11.0-alpha3"]
:dependencies [[org.clojure/clojure "1.11.0-beta1"]
[borkdude/edamame "0.0.19"]
[borkdude/graal.locking "0.0.2"]
[org.clojure/tools.cli "1.0.206"]
[cheshire "5.10.1"]
[cheshire "5.10.2"]
[nrepl/bencode "1.1.0"]
[borkdude/sci.impl.reflector "0.0.1"]
[org.clojure/core.async "1.4.627"]
[org.clojure/test.check "1.1.0"]
[org.clojure/core.async "1.5.648"]
[org.clojure/test.check "1.1.1"]
[com.github.clj-easy/graal-build-time "0.1.0"]
[rewrite-clj/rewrite-clj "1.0.699-alpha"]]
:plugins [[org.kipz/lein-meta-bom "0.1.1"]]
:metabom {:jar-name "metabom.jar"}
:profiles {:feature/xml {:source-paths ["feature-xml"]
:dependencies [[org.clojure/data.xml "0.2.0-alpha6"]]}
:feature/yaml {:source-paths ["feature-yaml"]
@ -42,7 +44,7 @@
:feature/csv {:source-paths ["feature-csv"]
:dependencies [[org.clojure/data.csv "1.0.0"]]}
:feature/transit {:source-paths ["feature-transit"]
:dependencies [[com.cognitect/transit-clj "1.0.324"]]}
:dependencies [[com.cognitect/transit-clj "1.0.329"]]}
:feature/datascript {:source-paths ["feature-datascript"]
:dependencies [[datascript "1.0.1"]]}
:feature/httpkit-client {:source-paths ["feature-httpkit-client"]

View file

@ -1 +1 @@
0.7.0
0.7.4

View file

@ -1 +1 @@
0.7.1-SNAPSHOT
0.7.5-SNAPSHOT

View file

@ -14,20 +14,20 @@
"depstar/src" "process/src"
"deps.clj/src" "deps.clj/resources"
"resources" "sci/resources"],
:deps {org.clojure/clojure {:mvn/version "1.11.0-alpha3"},
:deps {org.clojure/clojure {:mvn/version "1.11.0-beta1"},
borkdude/sci {:local/root "sci"}
babashka/babashka.curl {:local/root "babashka.curl"}
babashka/fs {:local/root "fs"}
babashka/babashka.core {:local/root "babashka.core"}
borkdude/graal.locking {:mvn/version "0.0.2"},
org.clojure/core.async {:mvn/version "1.4.627"},
org.clojure/core.async {:mvn/version "1.5.648"},
org.clojure/tools.cli {:mvn/version "1.0.206"},
org.clojure/data.csv {:mvn/version "1.0.0"},
cheshire/cheshire {:mvn/version "5.10.1"}
cheshire/cheshire {:mvn/version "5.10.2"}
org.clojure/data.xml {:mvn/version "0.2.0-alpha6"}
clj-commons/clj-yaml {:mvn/version "0.7.107"}
com.cognitect/transit-clj {:mvn/version "1.0.324"}
org.clojure/test.check {:mvn/version "1.1.0"}
com.cognitect/transit-clj {:mvn/version "1.0.329"}
org.clojure/test.check {:mvn/version "1.1.1"}
nrepl/bencode {:mvn/version "1.1.0"}
seancorfield/next.jdbc {:mvn/version "1.1.610"}
org.postgresql/postgresql {:mvn/version "42.2.18"}
@ -55,8 +55,7 @@
:extra-deps {org.clj-commons/clj-http-lite {:mvn/version "0.4.392"}
org.babashka/spec.alpha {:git/url "https://github.com/babashka/spec.alpha"
:sha "0dec1f88cbde74a0470b454396f09a03adb4ae39"}
lambdaisland/regal {:git/url "https://github.com/lambdaisland/regal"
:sha "f902d2c43121f9e1c48603d6eb99f5900eb6a9f6"}
lambdaisland/regal {:mvn/version "0.0.143"}
weavejester/medley {:git/url "https://github.com/weavejester/medley"
:sha "a4e5fb5383f5c0d83cb2d005181a35b76d8a136d"}
cprop/cprop {:mvn/version "0.1.16"}
@ -69,16 +68,16 @@
henryw374/cljc.java-time
{:git/url "https://github.com/henryw374/cljc.java-time.git"
:sha "e3d184b78e933322b3fcaa6ca66cbb8f42a6b35c"}
camel-snake-kebab/camel-snake-kebab {:mvn/version "0.4.1"}
camel-snake-kebab/camel-snake-kebab {:mvn/version "0.4.2"}
aero/aero {:mvn/version "1.1.6"}
org.clojure/data.generators {:mvn/version "1.0.0"}
honeysql/honeysql {:mvn/version "1.0.444"}
com.github.seancorfield/honeysql {:mvn/version "2.0.0-rc2"}
minimallist/minimallist {:mvn/version "0.0.6"}
circleci/bond {:mvn/version "0.4.0"}
version-clj/version-clj {:mvn/version "2.0.1"}
honeysql/honeysql {:mvn/version "1.0.461"}
com.github.seancorfield/honeysql {:mvn/version "2.2.840"}
minimallist/minimallist {:mvn/version "0.0.10"}
circleci/bond {:mvn/version "0.6.0"}
version-clj/version-clj {:mvn/version "2.0.2"}
gaka/gaka {:mvn/version "0.3.0"}
failjure/failjure {:mvn/version "2.1.1"}
failjure/failjure {:mvn/version "2.2.0"}
io.helins/binf {:mvn/version "1.1.0-beta0"}
rm-hull/jasentaa {:mvn/version "0.2.5"}
slingshot/slingshot {:mvn/version "0.12.2"}
@ -104,7 +103,30 @@
listora/again {:mvn/version "1.0.0"}
org.clojure/tools.gitlibs {:mvn/version "2.4.172"}
environ/environ {:mvn/version "1.2.0"}
<<<<<<< HEAD
table/table {:git/url "https://github.com/cldwalker/table", :sha "55aef3d5fced682942af811bf5d642f79fb87688"}}
=======
table/table {:git/url "https://github.com/cldwalker/table", :sha "f6293c5f3dac1dd6f525a80fc80930f8ccdf16b7"}
markdown-clj/markdown-clj {:mvn/version "1.10.8"}
org.clojure/tools.namespace {:git/url "https://github.com/babashka/tools.namespace", :sha "a13b037215e21a2e71aa34b27e1dd52c801a2a7b"}
medley/medley {:mvn/version "1.3.0"}
io.github.cognitect-labs/test-runner {:git/tag "v0.5.0", :git/sha "b3fd0d2"}
borkdude/missing.test.assertions {:git/url "https://github.com/borkdude/missing.test.assertions", :sha "603cb01bee72fb17addacc53c34c85612684ad70"}
dev.nubank/docopt {:mvn/version "0.6.1-fix7"}
testdoc/testdoc {:mvn/version "1.4.1"}
org.clojars.lispyclouds/contajners {:mvn/version "0.0.4"}
borkdude/rewrite-edn {:mvn/version "0.1.0"}
clojure-term-colors/clojure-term-colors {:mvn/version "0.1.0"}
io.aviso/pretty {:mvn/version "1.1.1"}
progrock/progrock {:mvn/version "0.1.2"}
djblue/portal {:mvn/version "0.19.0"}
com.wsscode/cljc-misc {:mvn/version "2021.10.16"}
edn-query-language/eql {:mvn/version "2021.07.18"}
meta-merge/meta-merge {:mvn/version "1.0.0"}
com.exoscale/lingo {:mvn/version "1.0.0-alpha14"}
io.github.swirrl/dogstatsd {:mvn/version "0.1.39"}
org.clojure/algo.monads {:mvn/version "0.1.6"}}
>>>>>>> array-play
:classpath-overrides {org.clojure/clojure nil
org.clojure/spec.alpha nil}}
:clj-nvd

2
sci

@ -1 +1 @@
Subproject commit 6ad100c7376bfac0f58ac12576caa805e2026d33
Subproject commit dd4a1f31e725ee1d2d1e95d3c0cf107925e8f9ce

View file

@ -1,21 +1,29 @@
#!/usr/bin/env bb
;; Adds a library to bb-tested-libs.edn to be tested given a library version and
;; git repository. Optionally takes a --test to then test the added library.
;; Adds a library to bb-tested-libs.edn and libraries.csv and optionally run its
;; tests. There are two modes to this script - automatic (default) and manual.
;; The script defaults to automatically copying tests as this normally works.
;; There are several options to specify where the library is including
;; --git-url, --dir and --test-directories. See --help for more. In manual mode,
;; tests are manually added outside of the script and the script is run to add
;; the library to library lists.
(ns add-libtest
(:require [babashka.deps :as deps]
[babashka.fs :as fs]
[babashka.tasks :refer [shell]]
[org.httpkit.client :as http]
[clojure.string :as str]
[clojure.java.io :as io]
[clojure.tools.cli :as cli]
[clojure.edn :as edn]))
(deps/add-deps '{:deps {org.clojure/tools.gitlibs {:mvn/version "2.4.172"}
borkdude/rewrite-edn {:mvn/version "0.1.0"}}})
borkdude/rewrite-edn {:mvn/version "0.1.0"}
org.clojure/data.csv {:mvn/version "1.0.0"}}})
(require '[clojure.tools.gitlibs :as gl])
(require '[borkdude.rewrite-edn :as r])
(require '[clojure.data.csv :as csv])
;; CLI Utils
;; =========
@ -53,48 +61,67 @@
(let [nodes (-> "deps.edn" slurp r/parse-string)]
(spit "deps.edn"
(str (r/assoc-in nodes
[:aliases :lib-tests :extra-deps (symbol lib-name)]
[:aliases :lib-tests :extra-deps lib-name]
lib-coordinate)))))
(defn- default-test-dir
[lib-root-dir]
(some #(when (fs/exists? (fs/file lib-root-dir %))
(str (fs/file lib-root-dir %)))
;; Most common test dir
["test"
;; official clojure repos like https://github.com/clojure/tools.gitlibs
"src/test/clojure"]))
(defn- copy-tests
[git-url lib-name {:keys [directory branch]}]
[git-url lib-name {:keys [directory branch test-directories]}]
(let [lib-dir (if branch
(gl/procure git-url lib-name branch)
(or (gl/procure git-url lib-name "master")
(gl/procure git-url lib-name "main")))
lib-root-dir (if directory
(fs/file lib-dir directory) lib-dir)
test-dir (some #(when (fs/exists? (fs/file lib-root-dir %))
(str (fs/file lib-root-dir %)))
;; Search common test dirs
["test"
;; official clojure repos like https://github.com/clojure/tools.gitlibs
"src/test/clojure"])]
(when-not test-dir
(error "No test dir found"))
(shell "cp -R" (str test-dir fs/file-separator) "test-resources/lib_tests/")
(gl/procure git-url lib-name "main")
(throw (ex-info "Unable to clone git-url" {}))))
_ (println "Git clone is at" lib-dir)
lib-root-dir (if directory (fs/file lib-dir directory) lib-dir)
test-dirs (if test-directories
(map #(when (fs/exists? (fs/file lib-root-dir %))
(str (fs/file lib-root-dir %)))
test-directories)
(some-> (default-test-dir lib-root-dir) vector))]
(when (empty? test-dirs)
(error "No test directories found"))
(doseq [test-dir test-dirs]
(shell "cp -R" (str test-dir fs/file-separator) "test-resources/lib_tests/"))
{:lib-dir lib-dir
:test-dir test-dir}))
:test-dirs test-dirs}))
(defn- default-test-namespaces
[test-dir]
(let [relative-test-files (map #(str (fs/relativize test-dir %))
(fs/glob test-dir "**/*.{clj,cljc}"))]
(when (empty? relative-test-files)
(error (str "No test files found in " test-dir)))
(map #(-> %
(str/replace fs/file-separator ".")
(str/replace "_" "-")
(str/replace-first #"\.clj(c?)$" "")
symbol)
relative-test-files)))
(defn- add-lib-to-tested-libs
[lib-name git-url {:keys [lib-dir test-dir]} options]
(let [git-sha (fs/file-name lib-dir)
relative-test-files (map #(str (fs/relativize test-dir %))
(fs/glob test-dir "**/*.{clj,cljc}"))
_ (when (empty? relative-test-files)
(error "No test files found"))
namespaces (map #(-> %
(str/replace fs/file-separator ".")
(str/replace "_" "-")
(str/replace-first #"\.clj(c?)$" "")
symbol)
relative-test-files)
lib (merge
{:git-sha git-sha
:git-url git-url
:test-namespaces namespaces}
;; Options needed to update libs
(select-keys options [:branch :directory]))
[lib-name git-url {:keys [lib-dir test-dirs]} options]
(let [namespaces (or (get-in options [:manually-added :test-namespaces])
(mapcat default-test-namespaces test-dirs))
default-lib (merge
{:git-url git-url
:test-namespaces namespaces}
;; Options needed to update libs
(select-keys options [:branch :directory :test-directories]))
lib (if (:manually-added options)
(-> default-lib
(merge (:manually-added options))
(assoc :manually-added true))
(assoc default-lib
:git-sha (fs/file-name lib-dir)))
nodes (-> "test-resources/lib_tests/bb-tested-libs.edn" slurp r/parse-string)]
(spit "test-resources/lib_tests/bb-tested-libs.edn"
(str (r/assoc-in nodes
@ -102,25 +129,63 @@
lib)))
namespaces))
(defn- fetch-artifact
"Using the clojars api to get a library's git url doesn't always work. A
possibly more reliable data source could be the scm urls in this POM feed -
https://github.com/clojars/clojars-web/wiki/Data#useful-extracts-from-the-poms"
[artifact]
(let [url (str "https://clojars.org/api/artifacts/" artifact)
_ (println "GET" url "...")
resp @(http/get url {:headers {"Accept" "application/edn"}})]
(if (= 200 (:status resp))
(-> resp :body slurp edn/read-string)
(error (str "Response failed and returned " (pr-str resp))))))
(defn- get-lib-map
[deps-string options]
;; if deps-string is artifact name
(if (re-matches #"\S+/\S+" deps-string)
(let [artifact-edn (fetch-artifact deps-string)]
{:lib-name (symbol deps-string)
:lib-coordinate {:mvn/version (:latest_version artifact-edn)}
:git-url (or (:git-url options) (:homepage artifact-edn))})
(let [deps-map (edn/read-string deps-string)
_ (when (or (not (map? deps-map)) (not= 1 (count deps-map)))
(error "Deps map must have one key"))
lib-coordinate (-> deps-map vals first)]
{:lib-name (ffirst deps-map)
:lib-coordinate lib-coordinate
:git-url (or (:git/url lib-coordinate) (:git-url options))})))
(defn- write-lib-to-csv
"Updates libraries.csv with latest bb-tested-libs.edn"
[]
(let [libs (-> "test-resources/lib_tests/bb-tested-libs.edn" slurp edn/read-string)
rows (sort-by first
(map (fn [[name {:keys [git-url]}]]
[name git-url]) libs))]
(with-open [w (io/writer "doc/libraries.csv")]
(csv/write-csv w (into [["maven-name" "git-url"]] rows)))))
(defn- add-libtest*
[args options]
(let [[deps-string git-url] args
deps-map (edn/read-string deps-string)
_ (when (not= 1 (count deps-map))
(error "Deps map must have one key"))
lib-name (ffirst deps-map)
lib-coordinate (deps-map lib-name)
_ (add-lib-to-deps lib-name lib-coordinate)
dirs (copy-tests git-url lib-name options)
(let [[artifact-or-deps-string] args
{:keys [lib-name lib-coordinate git-url]}
(get-lib-map artifact-or-deps-string options)
_ (when (nil? git-url)
(error "git-url is required. Please specify with --git-url"))
_ (when-not (:manually-added options) (add-lib-to-deps lib-name lib-coordinate))
dirs (when-not (:manually-added options) (copy-tests git-url lib-name options))
namespaces (add-lib-to-tested-libs lib-name git-url dirs options)]
(println "Added lib" lib-name "which tests the following namespaces:" namespaces)
(write-lib-to-csv)
(when (:test options)
(apply shell "script/lib_tests/run_all_libtests" namespaces))))
(defn add-libtest
[{:keys [arguments options summary]}]
(if (or (< (count arguments) 2) (:help options))
(print-summary "DEPS-MAP GIT-URL " summary)
(if (or (< (count arguments) 1) (:help options))
(print-summary "ARTIFACT-OR-DEPS-MAP " summary)
(add-libtest* arguments options)))
(def cli-options
@ -129,7 +194,13 @@
;; https://github.com/weavejester/environ/tree/master/environ used this option
["-d" "--directory DIRECTORY" "Directory where library is located"]
;; https://github.com/reifyhealth/specmonstah used this option
["-b" "--branch BRANCH" "Default branch for git url"]])
["-b" "--branch BRANCH" "Default branch for git url"]
["-g" "--git-url GITURL" "Git url for artifact. Defaults to homepage on clojars"]
["-m" "--manually-added LIB-MAP" "Only add library to edn file with LIB-MAP merged into library entry"
:parse-fn edn/read-string :validate-fn map?]
;; https://github.com/jeaye/orchestra used this option
["-T" "--test-directories TEST-DIRECTORY" "Directories where library tests are located"
:multi true :update-fn conj]])
(when (= *file* (System/getProperty "babashka.file"))
(run-command add-libtest *command-line-args* cli-options))

View file

@ -12,16 +12,26 @@
str/trim)))
(defn release [& args]
(let [current-version (-> (slurp "resources/BABASHKA_VERSION")
str/trim)
ght (System/getenv "GITHUB_TOKEN")
(let [ght (System/getenv "GITHUB_TOKEN")
file (first args)
branch (current-branch)]
branch (current-branch)
current-version
(-> (slurp "resources/BABASHKA_VERSION")
str/trim)]
(if (and ght (contains? #{"master" "main"} branch))
(do (assert file "File name must be provided")
(ghr/overwrite-asset {:org "babashka"
:repo "babashka"
:file file
:tag (str "v" current-version)}))
:tag (str "v" current-version)
:draft true})
(ghr/overwrite-asset {:org "babashka"
:repo "babashka-dev-builds"
:file file
:tag (str "v" current-version)
;; do not set, because we are posting to another repo
:target-commitish false
:draft false
:prerelease true}))
(println "Skipping release artifact (no GITHUB_TOKEN or not on main branch)"))
nil))

View file

@ -51,9 +51,9 @@
;; OR
;;
;; We could have them as environment variables
(def current-graal-version "21.2.0")
(def current-graal-version "21.3.0")
(def current-java-version "java11")
(def valid-graal-bumps ["19.3.2" "20.1.0" "20.2.0" "20.3.0" "21.0.0" "21.1.0" "21.2.0" "21.3.0"])
(def valid-graal-bumps ["19.3.2" "20.1.0" "20.2.0" "20.3.0" "21.0.0" "21.1.0" "21.2.0" "21.3.0" "22.0.0.2"])
(def valid-java-bumps ["java8" "java11"])
(def cl-options

View file

@ -33,10 +33,13 @@ rm -rf resources/*.class
# "$GRAALVM_HOME/bin/javac" -cp "$SVM_JAR" resources/CutOffMisc.java
if [ -z "$BABASHKA_JAR" ]; then
lein with-profiles +reflection,+native-image "do" run
lein "do" clean, uberjar
lein "do" clean, uberjar, metabom
BABASHKA_JAR=${BABASHKA_JAR:-"target/babashka-$BABASHKA_VERSION-standalone.jar"}
fi
# because script/test cleans target during ci before the jar can we saved
cp target/metabom.jar .
BABASHKA_BINARY=${BABASHKA_BINARY:-"bb"}
args=("-jar" "$BABASHKA_JAR"

View file

@ -2,7 +2,7 @@
set -euo pipefail
CLOJURE_TOOLS_VERSION="1.10.1.447"
CLOJURE_TOOLS_VERSION="1.10.3.1040"
install_dir="${1:-/usr/local}"
mkdir -p "$install_dir"

View file

@ -4,8 +4,4 @@ set EDN=lib_tests.edn
.\bb -f script/lib_tests/bb_edn_from_deps.clj %EDN%
set BABASHKA_EDN=%EDN%
%BB_CMD% -f test-resources/lib_tests/babashka/run_all_libtests.clj %*
set BABASHKA_EDN=
%BB_CMD% --config %EDN% --deps-root . -f test-resources/lib_tests/babashka/run_all_libtests.clj %*

View file

@ -165,5 +165,5 @@ cp deps.edn resources/META-INF/babashka/deps.edn
if [ -z "$BABASHKA_JAR" ]; then
lein with-profiles "$BABASHKA_LEIN_PROFILES,+reflection,-uberjar" do run
lein with-profiles "$BABASHKA_LEIN_PROFILES" do clean, uberjar
lein with-profiles "$BABASHKA_LEIN_PROFILES" do clean, uberjar, metabom
fi

View file

@ -73,12 +73,15 @@
{:name "toURI"}]}
java.util.Arrays
{:methods [{:name "copyOf"}
{:name "copyOfRange"}]}
{:name "copyOfRange"}
{:name "equals"}]}
;; this fixes clojure.lang.Reflector for Java 11
java.lang.reflect.AccessibleObject
{:methods [{:name "canAccess"}]}
java.lang.reflect.Method
{:methods [{:name "getName"}]}
java.lang.reflect.Array
{:methods [{:name "newInstance"}]}
java.net.Inet4Address
{:methods [{:name "getHostAddress"}]}
java.net.Inet6Address
@ -91,7 +94,9 @@
clojure.lang.RT
{:methods [{:name "aget"}
{:name "aset"}
{:name "aclone"}]}})
{:name "aclone"}]}
clojure.lang.Compiler
{:fields [{:name "specials"}]}})
(def custom-map
(cond->
@ -116,6 +121,10 @@
java.io.ByteArrayOutputStream
java.io.Closeable
java.io.Console
java.io.DataInput
java.io.DataInputStream
java.io.DataOutput
java.io.DataOutputStream
java.io.File
java.io.FileFilter
java.io.FilenameFilter
@ -392,6 +401,7 @@
;; visible in the native image.
:instance-checks [clojure.lang.AMapEntry ;; for proxy
clojure.lang.APersistentMap ;; for proxy
clojure.lang.APersistentSet
clojure.lang.AReference
clojure.lang.Associative
clojure.lang.Atom

View file

@ -1,7 +1,7 @@
(ns babashka.impl.clojure.core
{:no-doc true}
(:refer-clojure :exclude [future read+string clojure-version with-precision
send-via send send-off sync])
send-via send send-off sync into-array])
(:require [babashka.impl.common :as common]
[borkdude.graal.locking :as locking]
[clojure.core :as c]
@ -142,6 +142,21 @@
[_flags-ignored-for-now & body]
`(clojure.core/-run-in-transaction (fn [] ~@body)))
(defn into-array
"Returns an array with components set to the values in aseq. The array's
component type is type if provided, or the type of the first value in
aseq if present, or Object. All values in aseq must be compatible with
the component type. Class objects for the primitive types can be obtained
using, e.g., Integer/TYPE."
{:added "1.0"
:static true}
([aseq]
(try (clojure.lang.RT/seqToTypedArray (seq aseq))
(catch IllegalArgumentException _
(clojure.lang.RT/seqToTypedArray Object (seq aseq)))))
([type aseq]
(clojure.lang.RT/seqToTypedArray type (seq aseq))))
(def core-extras
{;; agents
'agent (copy-core-var agent)
@ -201,6 +216,9 @@
'random-uuid (sci/copy-var random-uuid clojure-core-ns)
'NaN? (sci/copy-var NaN? clojure-core-ns)
'infinite? (sci/copy-var infinite? clojure-core-ns)
'iteration (sci/copy-var iteration clojure-core-ns)
'abs (sci/copy-var abs clojure-core-ns)
'StackTraceElement->vec (sci/copy-var StackTraceElement->vec clojure-core-ns)
'memfn (sci/copy-var memfn clojure-core-ns)}
'memfn (sci/copy-var memfn clojure-core-ns)
'into-array (sci/copy-var into-array clojure-core-ns)}
)

View file

@ -104,10 +104,12 @@ by default when a new command-line REPL is started."} repl-requires
(set! *3 *2)
(set! *2 *1)
(set! *1 value)
(try
(print value)
(catch Throwable e
(throw (ex-info nil {:clojure.error/phase :print-eval-result} e)))))))
(try (print value)
(catch Throwable e
(throw (ex-info (ex-message e)
(assoc (meta input)
:file "<repl>"
:type :sci/error) e)))))))
(catch Throwable e
(caught e)
(set! *e e))))]

View file

@ -0,0 +1,6 @@
(ns babashka.impl.clojure.math
(:require [clojure.math]
[sci.core :as sci]))
(def mns (sci/create-ns 'clojure.math nil))
(def math-namespace (sci/copy-ns clojure.math mns))

View file

@ -1,6 +1,8 @@
(ns babashka.impl.deps
(:require [babashka.deps :as bdeps]
[babashka.fs :as fs]
[babashka.impl.classpath :as cp]
[babashka.impl.common :refer [bb-edn]]
[borkdude.deps :as deps]
[clojure.string :as str]
[sci.core :as sci]))
@ -42,8 +44,8 @@
paths)))
#_(merge-default-deps '{:deps {medley/medley nil}
:aliases {:foo {medley/medley nil}}}
'{medley/medley {:mvn/version "1.3.0"}})
:aliases {:foo {medley/medley nil}}}
'{medley/medley {:mvn/version "1.3.0"}})
;;;; end merge edn files
@ -58,28 +60,41 @@
([deps-map] (add-deps deps-map nil))
([deps-map {:keys [:aliases :env :extra-env :force]}]
(when-let [paths (:paths deps-map)]
(cp/add-classpath (str/join cp/path-sep paths)))
(when-let [deps-map (not-empty (dissoc deps-map :paths :tasks :raw :min-bb-version))]
(binding [*print-namespace-maps* false]
(let [deps-map (assoc-in deps-map [:aliases :org.babashka/defaults]
{:replace-paths [] ;; babashka sets paths manually
:classpath-overrides (cond->
'{org.clojure/clojure ""
org.clojure/spec.alpha ""}
;; only remove core specs when they are not mentioned in deps map
(not (str/includes? (str deps-map) "org.clojure/core.specs.alpha"))
(assoc 'org.clojure/core.specs.alpha ""))})
args (list "-Srepro" ;; do not include deps.edn from user config
"-Spath" "-Sdeps" (str deps-map)
"-Sdeps-file" "") ;; we reset deps file so the local deps.edn isn't used
args (if force (cons "-Sforce" args) args)
args (concat args [(str "-A:" (str/join ":" (cons ":org.babashka/defaults" aliases)))])
cp (with-out-str (binding [deps/*env* env
deps/*extra-env* extra-env]
(apply deps/-main args)))
cp (str/trim cp)
cp (str/replace cp (re-pattern (str cp/path-sep "+$")) "")]
(cp/add-classpath cp))))))
(let [paths (if-let [deps-root (:deps-root @bb-edn)]
(let [deps-root (fs/absolutize deps-root)
paths (mapv #(str (fs/file deps-root %)) paths)]
paths)
paths)]
(cp/add-classpath (str/join cp/path-sep paths))))
(let [need-deps? (or (:deps deps-map)
(and (:aliases deps-map)
aliases))]
(when need-deps?
(let [deps-map (dissoc deps-map
;; paths are added manually above
;; extra-paths are added as :paths in tasks
:paths :tasks :raw :file :deps-root
:min-bb-version)]
(binding [*print-namespace-maps* false]
(let [deps-map (assoc-in deps-map [:aliases :org.babashka/defaults]
{:replace-paths [] ;; babashka sets paths manually
:classpath-overrides (cond->
'{org.clojure/clojure ""
org.clojure/spec.alpha ""}
;; only remove core specs when they are not mentioned in deps map
(not (str/includes? (str deps-map) "org.clojure/core.specs.alpha"))
(assoc 'org.clojure/core.specs.alpha ""))})
args (list "-Srepro" ;; do not include deps.edn from user config
"-Spath" "-Sdeps" (str deps-map)
"-Sdeps-file" "") ;; we reset deps file so the local deps.edn isn't used
args (if force (cons "-Sforce" args) args)
args (concat args [(str "-A:" (str/join ":" (cons ":org.babashka/defaults" aliases)))])
cp (with-out-str (binding [deps/*env* env
deps/*extra-env* extra-env]
(apply deps/-main args)))
cp (str/trim cp)
cp (str/replace cp (re-pattern (str cp/path-sep "+$")) "")]
(cp/add-classpath cp))))))))
(def deps-namespace
{'add-deps (sci/copy-var add-deps dns)

View file

@ -139,10 +139,6 @@
(ruler "Context")
(println ec)
(println))
(when-let [locals (and (:debug opts) (not-empty (:locals d)))]
(ruler "Locals")
(print-locals locals)
(println))
(when sci-error?
(when-let
[st (let [st (with-out-str

View file

@ -229,8 +229,7 @@
(defn format-task [init extra-paths extra-deps requires prog]
(format "
%s ;; extra-paths
%s ;; extra-deps
%s ;; deps
(ns %s %s)
(require '[babashka.tasks])
@ -251,12 +250,12 @@
%s
"
(if (seq extra-paths)
(format "(babashka.classpath/add-classpath \"%s\")" (str/join cp/path-sep extra-paths))
"")
(if (seq extra-deps)
(format "(babashka.deps/add-deps '%s)" (pr-str {:deps extra-deps}))
"")
(let [deps (cond-> {}
(seq extra-deps) (assoc :deps extra-deps)
(seq extra-paths) (assoc :paths extra-paths))]
(if (seq deps)
(format "(babashka.deps/add-deps '%s)" (pr-str deps))
""))
@rand-ns
(if (seq requires)
(format "(:require %s)" (str/join " " requires))
@ -271,13 +270,13 @@
depends (:depends task)]
(when (contains? processing task-name)
(throw (ex-info (str "Cyclic task: " task-name) {})))
(loop [deps (seq depends)]
(let [deps (remove #(contains? @processed %) deps)
order (vec (mapcat #(target-order tasks % processed (conj processing task-name)) deps))]
(if-not (contains? @processed task-name)
(do (vswap! processed conj task-name)
(conj order task-name))
order))))))
(let [deps (seq depends)
deps (remove #(contains? @processed %) deps)
order (vec (mapcat #(target-order tasks % processed (conj processing task-name)) deps))]
(if-not (contains? @processed task-name)
(do (vswap! processed conj task-name)
(conj order task-name))
order)))))
#_(defn tasks->dependees [task-names tasks]
(let [tasks->depends (zipmap task-names (map #(:depends (get tasks %)) task-names))]

View file

@ -0,0 +1,105 @@
(ns babashka.impl.uberscript
(:require [sci.core :as sci]))
(defn decompose-clause [clause]
(if (symbol? clause)
{:ns clause}
(when (seqable? clause)
(let [clause (if (= 'quote (first clause))
(second clause)
clause)
[ns & tail] clause]
(loop [parsed {:ns ns}
tail (seq tail)]
(if tail
(let [ftail (first tail)]
(case ftail
:as (recur (assoc parsed :as (second tail))
(nnext tail))
:refer
(let [refer (second tail)]
(if (seqable? refer)
(recur (assoc parsed :refer (second tail))
(nnext tail))
(recur parsed (nnext tail))))
;; default
(recur parsed
(nnext tail))))
parsed))))))
(defn recompose-clause [{:keys [:ns :as]}]
[ns :as as])
(defn process-ns
[_ctx ns]
(keep (fn [x]
(if (seqable? x)
(let [fx (first x)]
(when (identical? :require fx)
(let [decomposed (keep decompose-clause (rest x))
recomposed (map recompose-clause decomposed)]
(list* :require recomposed))))
x))
ns))
(defn keep-quoted [clauses]
(keep (fn [clause]
(when (and (seq? clause) (= 'quote (first clause)))
(second clause)))
clauses))
(defn process-require [_ctx req]
(let [quoted (keep-quoted (rest req))
decomposed (map decompose-clause quoted)]
(list* 'require (map (fn [clause]
(list 'quote (recompose-clause clause)))
decomposed))))
(defn process-in-ns [_ctx req]
(let [quoted (keep-quoted (rest req))
quoted (map (fn [ns]
(list 'quote ns))
quoted)]
(when (clojure.core/seq quoted)
(list* 'in-ns quoted))))
(defn loc [rdr]
(str (when-let [f @sci/file]
(str f ":"))
(sci/get-line-number rdr)
":"
(sci/get-column-number rdr)))
(defn uberscript [{:keys [ctx expressions]}]
(let [ctx (assoc ctx :reload-all true)]
(sci/binding [sci/file @sci/file]
(doseq [expr expressions]
(let [rdr (sci/reader expr)]
(loop []
(let [next-val
(try (sci/parse-next ctx rdr)
;; swallow reader error
(catch Exception _e
(binding [*out* *err*]
(println "[babashka]" "Ignoring read error while assembling uberscript near"
(loc rdr)))))]
;; (.println System/err (pr-str next-val))
(when-not (= ::sci/eof next-val)
(if (seq? next-val)
(let [fst (first next-val)
expr (cond (= 'ns fst)
(process-ns ctx next-val)
(= 'require fst)
(process-require ctx next-val)
(= 'in-ns fst)
(process-in-ns ctx next-val))]
(when expr
(try
(sci/eval-form ctx expr)
;; swallow exception and continue
(catch Exception _e
(binding [*out* *err*]
(println "[babashka]" "Ignoring expression while assembling uberscript:"
expr "near" (loc rdr))))))
(recur))
(recur))))))))))

View file

@ -16,6 +16,7 @@
[babashka.impl.clojure.java.io :refer [io-namespace]]
[babashka.impl.clojure.java.shell :refer [shell-namespace]]
[babashka.impl.clojure.main :as clojure-main :refer [demunge]]
[babashka.impl.clojure.math :refer [math-namespace]]
[babashka.impl.clojure.stacktrace :refer [stacktrace-namespace]]
[babashka.impl.clojure.zip :refer [zip-namespace]]
[babashka.impl.common :as common]
@ -41,6 +42,7 @@
[babashka.impl.tasks :as tasks :refer [tasks-namespace]]
[babashka.impl.test :as t]
[babashka.impl.tools.cli :refer [tools-cli-namespace]]
[babashka.impl.uberscript :as uberscript]
[babashka.nrepl.server :as nrepl-server]
[babashka.wait :refer [wait-namespace]]
[clojure.edn :as edn]
@ -136,6 +138,8 @@ Global opts:
--debug Print debug information and internal stacktrace in case of exception.
--force Passes -Sforce to deps.clj, forcing recalculation of the classpath.
--init <file> Load file after any preloads and prior to evaluation/subcommands.
--config <file> Replacing bb.edn with file. Relative paths are resolved relative to file.
--deps-root <dir> Treat dir as root of relative paths in config.
Help:
@ -272,8 +276,8 @@ Use bb run --help to show this help output.
(let [f (io/file file)]
(if (.exists f)
(as-> (slurp file) x
;; remove shebang
(str/replace x #"^#!.*" ""))
;; remove shebang
(str/replace x #"^#!.*" ""))
(throw (Exception. (str "File does not exist: " file))))))
(defn load-file* [f]
@ -350,6 +354,7 @@ Use bb run --help to show this help output.
(let [opts (apply hash-map opts)]
(repl/start-repl! @common/ctx opts))) {:ns clojure-main-ns})}
'clojure.test t/clojure-test-namespace
'clojure.math math-namespace
'babashka.classpath classpath-namespace
'clojure.pprint pprint-namespace
'babashka.curl curl-namespace
@ -598,7 +603,9 @@ Use bb run --help to show this help output.
("--main", "-m",)
(let [options (next options)]
(assoc opts-map :main (first options)
:command-line-args (rest options)))
:command-line-args (if (= "--" (second options))
(nthrest options 2)
(rest options))))
("--run")
(parse-run-opts opts-map (next options))
("--tasks")
@ -631,21 +638,27 @@ Use bb run --help to show this help output.
(if options
(case (first options)
("--classpath" "-cp") (recur (nnext options) (assoc opts-map :classpath (second options)))
("--debug"
"--verbose" ;; renamed to --debug
) (recur (next options) (assoc opts-map :debug true))
"--verbose")
;; renamed to --debug
(recur (next options) (assoc opts-map :debug true))
("--init")
(recur (nnext options) (assoc opts-map :init (second options)))
("--config")
(recur (nnext options) (assoc opts-map :config (second options)))
("--deps-root")
(recur (nnext options) (assoc opts-map :deps-root (second options)))
[options opts-map])
[options opts-map])))
(defn parse-opts
([options] (parse-opts options nil))
([options opts-map]
(let [[options opts-map] (if opts-map
[options opts-map]
(parse-global-opts options))
opt (first options)
(let [opt (first options)
tasks (into #{} (map str) (keys (:tasks @common/bb-edn)))]
(if-not opt opts-map
;; FILE > TASK > SUBCOMMAND
@ -727,9 +740,13 @@ Use bb run --help to show this help output.
(or (contains? namespaces namespace)
(contains? sci-namespaces/namespaces namespace)))
""
(let [res (cp/source-for-namespace loader namespace nil)]
(when uberscript (swap! uberscript-sources conj (:source res)))
res)))
(when-let [res (cp/source-for-namespace loader namespace nil)]
(if uberscript
(do (swap! uberscript-sources conj (:source res))
(uberscript/uberscript {:ctx @common/ctx
:expressions [(:source res)]})
{})
res))))
(case namespace
clojure.spec.alpha
(binding [*out* *err*]
@ -833,7 +850,12 @@ Use bb run --help to show this help output.
uberjar [nil 0]
list-tasks [(tasks/list-tasks sci-ctx) 0]
print-deps [(print-deps/print-deps (:print-deps-format cli-opts)) 0]
uberscript
[nil (do (uberscript/uberscript {:ctx sci-ctx
:expressions expressions})
0)]
expressions
;; execute code
(sci/binding [sci/file abs-path]
(try
; when evaluating expression(s), add in repl-requires so things like
@ -871,7 +893,6 @@ Use bb run --help to show this help output.
clojure [nil (if-let [proc (bdeps/clojure command-line-args)]
(-> @proc :exit)
0)]
uberscript [nil 0]
:else [(repl/start-repl! sci-ctx) 0]))
1)]
(flush)
@ -902,23 +923,28 @@ Use bb run --help to show this help output.
(>= patch-current patch-min)))))))
(defn main [& args]
(let [bb-edn-file (or (System/getenv "BABASHKA_EDN")
(let [[args global-opts] (parse-global-opts args)
config (:config global-opts)
bb-edn-file (or config
"bb.edn")
bb-edn (or (when (fs/exists? bb-edn-file)
(let [raw-string (slurp bb-edn-file)
edn (edn/read-string raw-string)
edn (assoc edn :raw raw-string)]
(vreset! common/bb-edn edn)))
;; tests may have modified bb-edn
@common/bb-edn)
bb-edn (when (fs/exists? bb-edn-file)
(let [raw-string (slurp bb-edn-file)
edn (edn/read-string raw-string)
edn (assoc edn
:raw raw-string
:file bb-edn-file)
edn (if-let [deps-root (or (:deps-root global-opts)
(some-> config fs/parent))]
(assoc edn :deps-root deps-root)
edn)]
(vreset! common/bb-edn edn)))
min-bb-version (:min-bb-version bb-edn)]
(when min-bb-version
(when-not (satisfies-min-version? min-bb-version)
(binding [*out* *err*]
(println (str "WARNING: this project requires babashka "
min-bb-version " or newer, but you have: " version))))))
(let [opts (parse-opts args)]
(exec opts)))
min-bb-version " or newer, but you have: " version)))))
(exec (parse-opts args global-opts))))
(def musl?
"Captured at compile time, to know if we are running inside a

View file

@ -1,5 +1,18 @@
(ns my.impl1
(:require [clojure.string]))
(:require [babashka.pods :as pods]
[clojure.string :as str]))
;; uberscript parser can parse and skip this
(prn ::str/foo)
str/join
(alias 'a 'clojure.string)
::a/foo ;; no error either
(pods/load-pod 'clj-kondo/clj-kondo "2021.10.19")
(require '[pod.borkdude.clj-kondo :as clj-kondo])
(prn (some? clj-kondo/run!))
(defn impl-fn
"identity"

View file

@ -13,7 +13,7 @@
goog.string.format
[cljs.tools.reader.reader-types
:refer [source-logging-push-back-reader]]]))
;; TODO:
;; BB-TEST-PATCH
#_#?(:clj (:import [aero.core Deferred])))
(defn env [s]
@ -38,6 +38,8 @@
(if (= value :favorite) :chocolate :vanilla))
(deftest basic-test
;; BB-TEST-PATCH: This and several other test files were changed to work with
;; our dir structure
(let [config (read-config "test-resources/lib_tests/aero/config.edn")]
(is (= "Hello World!" (:greeting config))))
(testing "Reading empty config returns nil"

View file

@ -0,0 +1,23 @@
(ns aero.lumo-test
(:require
aero.core-test
[cljs.test :refer-macros [deftest is testing run-tests]]))
(def resolve-p (atom nil))
(def p (new js/Promise (fn [resolve reject]
(reset! resolve-p resolve))))
(defmethod cljs.test/report [:cljs.test/default :end-run-tests]
[m]
(@resolve-p m))
(defn -main [& argv]
(println "Testing with lumo")
(run-tests 'aero.core-test)
(-> p
(.then (fn [m]
(.exit (js/require "process")
(if (cljs.test/successful? m)
0
1))))))

View file

@ -1,15 +0,0 @@
(ns babashka.lambdaisland.regal-test
(:require [clojure.test :as t :refer [deftest is]]))
(prn :requiring :lambdaisland)
(require '[lambdaisland.regal :as regal])
(prn ::done :requiring :lambdaisland)
(def r [:cat
[:+ [:class [\a \z]]]
"="
[:+ [:not \=]]])
(deftest regal-test
(is (= "[a-z]+=[^=]+" (str (regal/regex r))))
(is (= "foo=bar" (re-matches (regal/regex r) "foo=bar"))))

View file

@ -1,10 +1,16 @@
(ns babashka.run-all-libtests
(:require [clojure.java.io :as io]
[clojure.string :as str]
(:require [babashka.core :refer [windows?]]
[clojure.edn :as edn]
[clojure.test :as t]))
[clojure.java.io :as io]
[clojure.test :as t :refer [*report-counters*]]))
#_(require 'clojure.spec.alpha)
(defmethod clojure.test/report :end-test-var [_m]
(when-let [rc *report-counters*]
(let [{:keys [:fail :error]} @rc]
(when (and (= "true" (System/getenv "BABASHKA_FAIL_FAST"))
(or (pos? fail) (pos? error)))
(println "=== Failing fast")
(System/exit 1)))))
(def ns-args (set (map symbol *command-line-args*)))
@ -23,86 +29,13 @@
(swap! status (fn [status]
(merge-with + status (dissoc m :type))))))))
(def windows? (-> (System/getProperty "os.name")
(str/lower-case)
(str/includes? "win")))
;; Standard test-runner for libtests
(let [lib-tests (edn/read-string (slurp (io/resource "bb-tested-libs.edn")))]
(doseq [{tns :test-namespaces skip-windows :skip-windows} (vals lib-tests)]
(when-not (and skip-windows (windows?))
(apply test-namespaces tns))))
;;;; clj-http-lite
(test-namespaces 'clj-http.lite.client-test)
;; ;;;; clojure.spec
(test-namespaces 'clojure.test-clojure.spec
'clojure.test-clojure.instr
'clojure.test-clojure.multi-spec)
;;;; regal
(test-namespaces 'babashka.lambdaisland.regal-test)
;;;; medley
(require '[medley.core :refer [index-by random-uuid]])
(prn (index-by :id [{:id 1} {:id 2}]))
(prn (random-uuid))
;;;; babashka.curl
; skip tests on Windows because of the :compressed thing
(when-not windows? (test-namespaces 'babashka.curl-test))
;;;; cprop
;; TODO: port to test-namespaces
(require '[cprop.core])
(require '[cprop.source :refer [from-env]])
(println (:cprop-env (from-env)))
;;;; clj-yaml
(test-namespaces 'clj-yaml.core-test)
;;;; clojure.data.zip
;; TODO: port to test-namespaces
(require '[clojure.data.xml :as xml])
(require '[clojure.zip :as zip])
(require '[clojure.data.zip.xml :refer [attr attr= xml1->]])
(def data (str "<root>"
" <character type=\"person\" name=\"alice\" />"
" <character type=\"animal\" name=\"march hare\" />"
"</root>"))
;; TODO: convert to test
(let [xml (zip/xml-zip (xml/parse (java.io.StringReader. data)))]
;(prn :xml xml)
(prn :alice-is-a (xml1-> xml :character [(attr= :name "alice")] (attr :type)))
(prn :animal-is-called (xml1-> xml :character [(attr= :type "animal")] (attr :name))))
;;;; clojure.data.csv
(test-namespaces 'clojure.data.csv-test)
;;;; clojure.math.combinatorics
(test-namespaces 'clojure.math.test-combinatorics)
;;;; deps.clj
;; TODO: port to test-namespaces
(require '[babashka.curl :as curl])
(spit "deps_test.clj"
(:body (curl/get "https://raw.githubusercontent.com/borkdude/deps.clj/master/deps.clj"
(if windows? {:compressed false} {}))))
(binding [*command-line-args* ["-Sdescribe"]]
(load-file "deps_test.clj"))
(.delete (io/file "deps_test.clj"))
;; Non-standard tests - These are tests with unusual setup around test-namespaces
;;;; doric
@ -112,48 +45,10 @@
((resolve 'doric.core/table) [:a :b] [{:a 1 :b 2}]))
(when (test-namespace? 'doric.test.core)
(test-doric-cyclic-dep-problem)
(test-namespaces 'doric.test.core))
;;;; cljc-java-time
(test-namespaces 'cljc.java-time-test)
;;;; camel-snake-kebab
(test-namespaces 'camel-snake-kebab.core-test)
;;;; aero
(test-namespaces 'aero.core-test)
;;;; clojure.data.generators
(test-namespaces 'clojure.data.generators-test)
;;;; honeysql
(test-namespaces 'honeysql.core-test 'honeysql.format-test)
;;;; minimallist
(test-namespaces 'minimallist.core-test)
;;;; bond
(test-namespaces 'bond.test.james)
;;;; version-clj
(test-namespaces 'version-clj.compare-test
'version-clj.core-test
'version-clj.split-test
'version-clj.via-use-test)
;;;; httpkit client
(test-namespaces 'httpkit.client-test)
(test-doric-cyclic-dep-problem))
;;;; babashka.process
(when-not windows?
(when-not (windows?)
;; test built-in babashka.process
(test-namespaces 'babashka.process-test)
@ -161,79 +56,6 @@
(require '[babashka.process] :reload)
(test-namespaces 'babashka.process-test))
(test-namespaces 'core-match.core-tests)
(test-namespaces 'hiccup.core-test)
(test-namespaces 'hiccup2.core-test)
(test-namespaces 'test-check.smoke-test)
(test-namespaces 'gaka.core-test)
(test-namespaces 'failjure.test-core)
(test-namespaces 'rewrite-clj.parser-test
'rewrite-clj.node-test
'rewrite-clj.zip-test
'rewrite-clj.paredit-test
'rewrite-clj.zip.subedit-test
'rewrite-clj.node.coercer-test)
(test-namespaces 'helins.binf.test)
(test-namespaces 'selmer.core-test)
(test-namespaces 'selmer.our-test)
(test-namespaces 'jasentaa.position-test
'jasentaa.worked-example-1
'jasentaa.worked-example-2
'jasentaa.collections-test
'jasentaa.parser.basic-test
'jasentaa.parser.combinators-test)
(test-namespaces 'honey.sql-test
'honey.sql.helpers-test
'honey.sql.postgres-test)
(test-namespaces 'slingshot.slingshot-test
'slingshot.support-test
;; TODO:
;; 'slingshot.test-test
)
(test-namespaces 'omniconf.core-test)
(test-namespaces 'crispin.core-test)
(test-namespaces 'multigrep.core-test)
(test-namespaces
;; TODO: env tests don't work because envoy lib isn't compatible with bb
#_'vault.env-test
'vault.lease-test
'vault.client.http-test
;; TODO:
;; failing tests in the following namespaces:
#_'vault.client.mock-test
#_'vault.secrets.kvv1-test
#_'vault.secrets.kvv2-test)
;; we don't really run any tests for java-http-clj yet, but we require the
;; namespaces to see if they at least load correctly
(test-namespaces 'java-http-clj.smoke-test)
(test-namespaces 'component.component-test)
(test-namespaces 'clj-commons.digest-test)
(test-namespaces 'hato.client-test)
(test-namespaces 'orchestra.core-test 'orchestra.expound-test 'orchestra.many-fns 'orchestra.reload-test)
(let [lib-tests (edn/read-string (slurp (io/resource "bb-tested-libs.edn")))]
(doseq [{tns :test-namespaces} (vals lib-tests)]
(apply test-namespaces tns)))
;;;; final exit code
(let [{:keys [:test :fail :error] :as m} @status]

View file

@ -8,7 +8,7 @@
mvxcvi/arrangement {:git-sha "360d29e7ae81abbf986b5a8e272f2086227d038d", :git-url "https://github.com/greglook/clj-arrangement", :test-namespaces (arrangement.core-test)}
clojure-csv/clojure-csv {:git-sha "b6bb882a3a9ac1f82e06eb2262ae7c8141935228", :git-url "https://github.com/davidsantiago/clojure-csv", :test-namespaces (clojure-csv.test.utils clojure-csv.test.core)}
environ/environ {:git-sha "aa90997b38bb8070d94dc4a00a14e656eb5fc9ae", :git-url "https://github.com/weavejester/environ", :test-namespaces (environ.core-test), :directory "environ"}
table/table {:git-sha "55aef3d5fced682942af811bf5d642f79fb87688", :git-url "https://github.com/cldwalker/table", :test-namespaces (table.width-test table.core-test)}
table/table {:git-sha "f6293c5f3dac1dd6f525a80fc80930f8ccdf16b7", :git-url "https://github.com/cldwalker/table", :test-namespaces (table.width-test table.core-test)}
com.stuartsierra/dependency {:git-sha "3a467918cd0e5b6ab775d344cfb2a80b56daad6d", :git-url "https://github.com/stuartsierra/dependency", :test-namespaces (com.stuartsierra.dependency-test)}
reifyhealth/specmonstah {:git-sha "a2b357009a3aa99a0c2d2361f3bbcd0b0e36505e", :git-url "https://github.com/reifyhealth/specmonstah", :test-namespaces (reifyhealth.specmonstah.spec-gen-test reifyhealth.specmonstah.test-data reifyhealth.specmonstah.core-test), :branch "develop"}
exoscale/coax {:git-sha "0d4212af7c07e4f05f74186f05df8a97777b43fe", :git-url "https://github.com/exoscale/coax", :test-namespaces (exoscale.coax-test)}
@ -16,4 +16,93 @@
org.clojars.askonomm/ruuter {:git-sha "78659212f95cac827efc816dfbdab8181c25fc3d", :git-url "https://github.com/askonomm/ruuter", :test-namespaces (ruuter.core-test)}
;; clojure.data.json-gen-test ommitted from test-namespaces b/c it hangs on stest/check
org.clojure/data.json {:git-sha "9f1c9ccf3fd3e5a39cfb7289d3d456e842ddf442", :git-url "https://github.com/clojure/data.json", :test-namespaces (clojure.data.json-test clojure.data.json-test-suite-test clojure.data.json-compat-0-1-test)}
io.replikativ/hasch {:git-sha "04d9c0bd34d86bad79502d8a6963eb2525a22b15", :git-url "https://github.com/replikativ/hasch", :test-namespaces (hasch.test)}}
io.replikativ/hasch {:git-sha "04d9c0bd34d86bad79502d8a6963eb2525a22b15", :git-url "https://github.com/replikativ/hasch", :test-namespaces (hasch.test)}
;; BB-TEST-PATCH: Removed markdown.md-file-test b/c tests hardcode path to test
;; files. Removed markdown.benchmark b/c it depends on criterium which isn't bb compatible
markdown-clj/markdown-clj {:git-sha "ac245d3049afa25a6d41fcb5ba5a268f52c610e4", :git-url "https://github.com/yogthos/markdown-clj", :test-namespaces (markdown.md-test)}
;; BB-TEST-PATCH: Removed clojure.tools.namespace.dir-test as it fails on windows
org.clojure/tools.namespace {:git-sha "a13b037215e21a2e71aa34b27e1dd52c801a2a7b", :git-url "https://github.com/babashka/tools.namespace", :test-namespaces (clojure.tools.namespace.test-helpers clojure.tools.namespace.dependency-test clojure.tools.namespace.find-test clojure.tools.namespace.move-test clojure.tools.namespace.parse-test), :branch "babashka"}
com.stuartsierra/component {:git-sha "9f9653d1d95644e3c30beadf8c8811f86758ea23", :git-url "https://github.com/stuartsierra/component", :test-namespaces (com.stuartsierra.component-test)}
slingshot/slingshot {:git-sha "6961ab0593ab9633c15b7697ffd43823090720be", :git-url "https://github.com/scgilardi/slingshot", :test-namespaces (slingshot.slingshot-test slingshot.support-test slingshot.test-test)}
rm-hull/jasentaa {:git-sha "f52a0e75cbdf1d2b72d9604232db264ff6473f12", :git-url "https://github.com/rm-hull/jasentaa", :test-namespaces (jasentaa.position-test jasentaa.worked-example-2 jasentaa.collections-test jasentaa.parser.basic-test jasentaa.parser.combinators-test jasentaa.test-helpers jasentaa.worked-example-1)}
failjure/failjure {:git-sha "c6e528c1eda6ad5eaab0f1fb2a97e766bf41fdd5", :git-url "https://github.com/adambard/failjure", :test-namespaces (failjure.test-core)}
gaka/gaka {:git-sha "2f264758881d6dc586b948ca8757134675f542a7", :git-url "https://github.com/cdaddr/gaka", :test-namespaces (gaka.core-test)}
version-clj/version-clj {:git-sha "9d86cd870f7e435fd6d593cb689790a22d8040a6", :git-url "https://github.com/xsc/version-clj", :test-namespaces (version-clj.compare-test version-clj.split-test version-clj.core-test version-clj.via-use-test)}
circleci/bond {:git-sha "0d389cfb4628341824bddbe8bf102f15ad25ad0d", :git-url "https://github.com/circleci/bond", :test-namespaces (bond.assertions-test bond.james-test bond.target-data)}
;; BB-TEST-PATCH: minimallist.generator-test excluded because generator ns can't be required
minimallist/minimallist {:git-sha "f10ebbd3c2b93e7579295618a7ed1e870c489bc4", :git-url "https://github.com/green-coder/minimallist", :test-namespaces (minimallist.util-test minimallist.core-test), :branch "all-work-and-no-play"}
aero/aero {:git-sha "743e9bc495425b4a4a7c780f5e4b09f6680b4e7a", :git-url "http://github.com/juxt/aero", :test-namespaces (aero.core-test)}
org.clojure/data.generators {:git-sha "bf65f99aa9dcabed7de7c09b74d71db208cf61ee", :git-url "https://github.com/clojure/data.generators", :test-namespaces (clojure.data.generators-test)}
camel-snake-kebab/camel-snake-kebab {:git-sha "d072c7fd242ab0becd4bb265622ded415f2a4b68", :git-url "https://github.com/clj-commons/camel-snake-kebab", :test-namespaces (camel-snake-kebab.internals.string-separator-test camel-snake-kebab.extras-test camel-snake-kebab.core-test)}
;; BB-TEST-PATCH: Deleted cljs-test-opts.edn
henryw374/cljc.java-time {:git-sha "b9da12ea25e80a0e284a5bffd88ebcbf18fc3bf7", :git-url "https://github.com/henryw374/cljc.java-time", :test-namespaces (cljc.java-time-test)}
org.babashka/spec.alpha {:git-sha "6c4aed643daaf55c6f898d4915275704db683aa2", :git-url "https://github.com/babashka/spec.alpha", :test-namespaces (clojure.test-clojure.instr clojure.test-clojure.spec)}
;; BB-TEST-PATCH: Don't have 4 tests namespaces because they depend on
;; additional libs that aren't bb compatible e.g. instaparse and malli
lambdaisland/regal {:git-sha "d13f26dfdf37186ee86016ed144fc823c5b24c11", :git-url "https://github.com/lambdaisland/regal", :test-namespaces (lambdaisland.regal.test-util lambdaisland.regal-test)}
medley/medley {:git-sha "d723afcb18e1fae27f3b68a25c7a151569159a9e", :git-url "https://github.com/weavejester/medley", :test-namespaces (medley.core-test)}
clj-commons/clj-yaml {:git-sha "9c2d602ec6ab33da061575f52e3de1aff41f67f5", :git-url "https://github.com/clj-commons/clj-yaml", :test-namespaces (clj-yaml.core-test)}
org.clojure/data.csv {:git-sha "aa9b3bdd3a1d3f6a7fe12eaab76b45ef3f197ad5", :git-url "https://github.com/clojure/data.csv", :test-namespaces (clojure.data.csv-test)}
org.clojure/math.combinatorics {:git-sha "e555a45b5802cf5e8c43b4377628ef34a634554b", :git-url "https://github.com/clojure/math.combinatorics", :test-namespaces (clojure.math.test-combinatorics)}
doric/doric {:git-sha "8747fdce565187a5c368c575cf4ca794084b0a5c", :git-url "https://github.com/joegallo/doric", :test-namespaces (doric.test.core doric.test.readme doric.test.doctest)}
com.github.seancorfield/honeysql {:git-sha "6e4e1f6928450788353c181f32474d930d6afe84", :git-url "https://github.com/seancorfield/honeysql", :test-namespaces (honey.sql-test honey.sql.helpers-test honey.sql.postgres-test), :branch "develop"}
honeysql/honeysql {:git-sha "1137dd12350afdc30ad4976c3718279581390b36", :git-url "https://github.com/seancorfield/honeysql", :test-namespaces (honeysql.format-test honeysql.core-test), :branch "v1"}
; skip tests on Windows because of the :compressed thing
babashka/babashka.curl {:git-url "https://github.com/babashka/babashka.curl", :test-namespaces [babashka.curl-test], :skip-windows true, :manually-added true}
http-kit/http-kit {:git-url "https://github.com/http-kit/http-kit", :test-namespaces [httpkit.client-test], :manually-added true}
org.clojure/core.match {:git-url "https://github.com/clojure/core.match", :test-namespaces [core-match.core-tests], :manually-added true}
hiccup/hiccup {:git-url "http://github.com/weavejester/hiccup", :test-namespaces [hiccup.core-test hiccup2.core-test], :manually-added true}
org.clojure/test.check {:git-url "https://github.com/clojure/test.check", :test-namespaces [test-check.smoke-test], :manually-added true}
io.helins/binf {:git-url "https://github.com/helins/binf.cljc", :test-namespaces [helins.binf.test], :manually-added true}
selmer/selmer {:git-url "https://github.com/yogthos/Selmer", :test-namespaces [selmer.core-test selmer.our-test], :manually-added true}
com.grammarly/omniconf {:git-url "https://github.com/grammarly/omniconf", :test-namespaces [omniconf.core-test], :manually-added true}
crispin/crispin {:git-url "https://github.com/dunaj-project/crispin", :test-namespaces [crispin.core-test], :manually-added true}
clj-commons/multigrep {:git-url "https://github.com/clj-commons/multigrep", :test-namespaces [multigrep.core-test], :manually-added true}
org.clj-commons/digest {:git-url "https://github.com/clj-commons/clj-digest", :test-namespaces [clj-commons.digest-test], :manually-added true}
hato/hato {:git-url "https://github.com/gnarroway/hato", :test-namespaces [hato.client-test], :manually-added true}
java-http-clj/java-http-clj {:git-url "http://www.github.com/schmee/java-http-clj", :test-namespaces [java-http-clj.smoke-test], :manually-added true}
rewrite-clj/rewrite-clj {:git-url "https://github.com/clj-commons/rewrite-clj", :test-namespaces [rewrite-clj.parser-test rewrite-clj.node-test rewrite-clj.zip-test rewrite-clj.paredit-test rewrite-clj.zip.subedit-test rewrite-clj.node.coercer-test], :manually-added true}
;; TODO: env tests don't work because envoy lib isn't compatible with bb
;; TODO: failing tests in the following namespaces: vault.client.mock-test, vault.secrets.kvv1-test vault.secrets.kvv2-test
amperity/vault-clj {:git-url "https://github.com/amperity/vault-clj", :test-namespaces [vault.lease-test vault.client.http-test], :manually-added true}
orchestra/orchestra {:git-url "https://github.com/jeaye/orchestra", :test-namespaces (orchestra.make-fns orchestra.many-fns orchestra.expound-test orchestra.core-test orchestra.reload-test), :test-directories ("test/cljc" "test/clj"), :git-sha "81e5181f7b42e5e2763a2b37db17954f3be0314e"}
;; BB-TEST-PATCH: Deleted tasks.clj
org.clj-commons/clj-http-lite {:git-url "https://github.com/clj-commons/clj-http-lite", :test-namespaces (clj-http.lite.test-runner clj-http.lite.client-test), :test-directories ("bb"), :git-sha "6b53000df55ac05c4ff8e5047a5323fc08a52e8b"}
cprop/cprop {:git-url "https://github.com/tolitius/cprop", :test-namespaces [cprop.smoke-test], :manually-added true}
org.clojure/data.zip {:git-url "https://github.com/clojure/data.zip", :test-namespaces [clojure.data.zip-test], :manually-added true}
borkdude/deps {:git-url "https://github.com/borkdude/deps.clj", :test-namespaces [borkdude.deps.smoke-test], :manually-added true}
io.github.cognitect-labs/test-runner {:git-url "https://github.com/cognitect-labs/test-runner", :test-namespaces (cognitect.test-runner.samples-test cognitect.test-runner.sample-property-test cognitect.test-runner-test), :git-sha "cc75980b43011773162b485f46f939dc5fba91e4"}
borkdude/missing.test.assertions {:git-url "https://github.com/borkdude/missing.test.assertions", :test-namespaces (missing.test.assertions-test missing.test.old-methods), :git-sha "603cb01bee72fb17addacc53c34c85612684ad70"}
;; No tests to run
io.github.technomancy/limit-break {:git-url "https://github.com/technomancy/limit-break", :test-namespaces [], :manually-added true}
dev.nubank/docopt {:git-url "https://github.com/nubank/docopt.clj", :test-namespaces (docopt.core-test), :git-sha "2794195a7288002e8d8a44f7bc37180c9cca8971"}
;; BB-TEST-PATCH: Deleted unused resources/
testdoc/testdoc {:git-url "https://github.com/liquidz/testdoc", :test-namespaces (testdoc.style.repl-test testdoc.style.code-first-test testdoc.core-test), :git-sha "6b995ef25f3cc6450a1ce30f72baed371476f6eb"}
;; BB-TEST-PATCH: Remove contajners.core-test as it fails
org.clojars.lispyclouds/contajners {:git-url "https://github.com/lispyclouds/contajners", :test-namespaces (contajners.impl-test), :git-sha "d163637ff36d79995516d6705da1e9afc7b44764"}
;; Don't run tests b/c they depend on `psql`
douglass/clj-psql {:git-url "https://github.com/DarinDouglass/clj-psql", :test-namespaces [], :manually-added true}
;; Don't run tests b/c they depend on `ffmpeg`
ffclj/ffclj {:git-url "https://github.com/luissantos/ffclj", :test-namespaces [], :manually-added true}
;; BB-TEST-PATCH: Can't load deps for tests - expound.alpha-test, expound.spell-spec-test, expound.paths-test. Skip expound.printer-test as most tests fail
;; BB-TEST-PATCH: Deleted cljs_test.cljs and *.txt
expound/expound {:git-url "https://github.com/bhb/expound", :test-namespaces (expound.specs-test expound.print-length-test expound.test-utils expound.spec-gen expound.problems-test), :git-sha "589a7f69323dc0423197b346c75808e48e771427"}
;; BB-TEST-PATCH: Removed borkdude.rewrite-edn-test because it fails
borkdude/rewrite-edn {:git-url "https://github.com/borkdude/rewrite-edn", :test-namespaces [], :branch "63f09048a3ebbd48f86fa9626076e7e540cfb7ee", :git-sha "63f09048a3ebbd48f86fa9626076e7e540cfb7ee"}
clojure-term-colors/clojure-term-colors {:git-url "https://github.com/trhura/clojure-term-colors", :test-namespaces (clojure.term.colors-test), :git-sha "71620a5e121d51afe28c50c0aa14ceb4cbff7981"}
;; BB-TEST-PATCH: Removed io.aviso.exception-test because it can't load ns with clojure.lang.Compiler.
;; BB-TEST-PATCH: Deleted demo*.clj
;; BB-TEST-PATCH: Don't run on windows as most binary tests fail
io.aviso/pretty {:git-url "https://github.com/AvisoNovate/pretty", :test-namespaces (io.aviso.binary-test), :git-sha "155926f991f94addaf6f5c8621748924ab144988" :skip-windows true}
progrock/progrock {:git-url "https://github.com/weavejester/progrock", :test-namespaces (progrock.core-test), :git-sha "9c277a3244c52bfde19c21add327d6e20b94fdf5"}
;; Don't run portal.jvm-test as it depends on headless chrome
djblue/portal {:git-url "https://github.com/djblue/portal", :test-namespaces (portal.test-runner portal.runtime.cson-test portal.runtime.fs-test portal.e2e portal.bench), :git-sha "64e4624bcf3bee2dd47e3d8e47982c709738eb11"}
integrant/integrant {:git-url "https://github.com/weavejester/integrant", :test-namespaces (integrant.test.foo integrant.test.quz integrant.test.bar integrant.test.baz integrant.core-test), :git-sha "32a46f5dca8a6b563a6dddf88bec887be3201b08"}
com.wsscode/cljc-misc {:git-url "https://github.com/wilkerlucio/cljc-misc", :test-namespaces (com.wsscode.misc.uuid-test com.wsscode.misc.macros-test com.wsscode.misc.math-test com.wsscode.misc.coll-test com.wsscode.misc.refs-test), :git-sha "dc8e31a200f9cacf86af10b63e40fcb448c259f4"}
edn-query-language/eql {:git-url "https://github.com/edn-query-language/eql", :test-namespaces (edn-query-language.core-test), :git-sha "0d4f9745d98c3d20b81bb4bdce3e8e15db7fd094"}
meta-merge/meta-merge {:git-url "https://github.com/weavejester/meta-merge", :test-namespaces (meta-merge.core-test), :git-sha "c968c38baccd4219fe0ba592d89af37ea8e426bf"}
com.exoscale/lingo {:git-url "https://github.com/exoscale/lingo", :test-namespaces (exoscale.lingo.test.core-test), :git-sha "30b5084fab28d24c99ec683e21535366910d9f2f" :skip-windows true}
io.github.swirrl/dogstatsd {:git-url "https://github.com/swirrl/dogstatsd", :test-namespaces (swirrl.dogstatsd-test), :git-sha "e110caae452cd1185e65e389a359b69502076d61"}
org.clojure/algo.monads {:git-url "https://github.com/clojure/algo.monads", :test-namespaces (clojure.algo.test-monads), :git-sha "3a985b0b099110b1654d568fecf597bc9c8d1ff5"}
io.lambdaforge/datalog-parser {:git-url "https://github.com/lambdaforge/datalog-parser", :test-namespaces (datalog.parser.pull-test datalog.parser.test.util datalog.parser.impl-test datalog.parser-test datalog.unparser-test), :git-sha "02d193f397afc3f93da704e7c6c850b194f0e797"}
clj-stacktrace/clj-stacktrace {:git-url "https://github.com/mmcgrana/clj-stacktrace", :test-namespaces (clj-stacktrace.repl-test clj-stacktrace.core-test), :git-sha "94dc2dd748710e79800e94b713e167e5dc525717"}}

View file

@ -0,0 +1,121 @@
(ns bond.assertions-test
(:require [clojure.test :refer (deftest is testing)]
[bond.assertions :as assertions]
[bond.james :as bond :include-macros true]
[bond.target-data :as target]))
(deftest called?-works
(testing "a spy was called directly"
(bond/with-spy [target/foo]
(target/foo 1)
(is (assertions/called? target/foo))))
(testing "a spy was called indirectly"
(bond/with-spy [target/foo]
(target/foo-caller 1)
(is (assertions/called? target/foo))))
(testing "a spy was not called"
(bond/with-spy [target/foo]
(is (not (assertions/called? target/foo)))))
(testing "called? fails when its argument is not spied"
(is (thrown? IllegalArgumentException
(assertions/called? target/foo)))))
(deftest called-times?-works
(testing "the number of times a spy was called"
(bond/with-spy [target/foo]
(target/foo-caller 1)
(is (assertions/called-times? target/foo 1))
(target/foo 2)
(is (assertions/called-times? target/foo 2))))
(testing "the number of times a spy was not called"
(bond/with-spy [target/foo]
(target/foo-caller 1)
(is (not (assertions/called-times? target/foo 2)))
(target/foo-caller 2)
(is (not (assertions/called-times? target/foo 1)))))
(testing "called-times? fails when its argument is not spied"
(is (thrown? IllegalArgumentException
(assertions/called-times? target/foo 0)))))
(deftest called-with-args?-works
(testing "an assertion for calling a spy with args"
(bond/with-spy [target/foo
target/bar]
(target/foo-caller 1)
(is (assertions/called-with-args? target/foo [[1]]))
(is (not (assertions/called-with-args? target/foo [[2]])))
(is (not (assertions/called-with-args? target/bar [[1]])))
(is (not (assertions/called-with-args? target/foo [[1 2]])))))
(testing "an assertion for calling a spy multiple times with args"
(bond/with-spy [target/foo]
(target/foo-caller 1)
(target/foo-caller 2)
(is (assertions/called-with-args? target/foo [[1] [2]]))))
(testing "called-with-args? fails when its argument is not spied"
(is (thrown? IllegalArgumentException
(assertions/called-with-args? target/foo [])))))
(deftest called-once-with-args?-works
(testing "an assertion for calling a spy once with args"
(bond/with-spy [target/foo]
(target/foo 1)
(is (assertions/called-once-with-args? target/foo [1]))
(is (not (assertions/called-once-with-args? target/foo [2])))))
(testing "an assertion for calling a spy twice with args"
(bond/with-spy [target/foo]
(target/foo 1)
(target/foo 2)
(is (not (assertions/called-once-with-args? target/foo [1])))
(is (not (assertions/called-once-with-args? target/foo [2])))))
(testing "an assertion for calling a spy indirectly once with args"
(bond/with-spy [target/foo]
(target/foo-caller 1)
(is (assertions/called-once-with-args? target/foo [1]))
(is (not (assertions/called-once-with-args? target/foo [2])))))
(testing "an assertion for a spy that was not called"
(bond/with-spy [target/foo]
(is (not (assertions/called-once-with-args? target/foo [])))))
(testing "called-once-with-args? fails when its argument is not spied"
(is (thrown? IllegalArgumentException
(assertions/called-once-with-args? target/foo [])))))
(deftest called-at-least-once-with-args?-works
(testing "an assertion for calling a spy multiple times"
(bond/with-spy [target/foo]
(target/foo 1)
(target/foo 2)
(is (assertions/called-at-least-once-with-args? target/foo [1]))
(is (assertions/called-at-least-once-with-args? target/foo [2]))
(is (not (assertions/called-at-least-once-with-args? target/foo [3])))))
(testing "an assertion for calling a spy multiple times with the same value"
(bond/with-spy [target/foo]
(target/foo 1)
(target/foo 1)
(is (assertions/called-at-least-once-with-args? target/foo [1]))
(is (not (assertions/called-at-least-once-with-args? target/foo [2])))))
(testing "an assertion for calling a spy once"
(bond/with-spy [target/foo]
(target/foo 1)
(is (assertions/called-at-least-once-with-args? target/foo [1]))
(is (not (assertions/called-at-least-once-with-args? target/foo [2])))))
(testing "an assertion for a spy that was not called"
(bond/with-spy [target/foo]
(is (not (assertions/called-at-least-once-with-args? target/foo [])))))
(testing "called-at-least-once-with-args? fails when its argument is not spied"
(is (thrown? IllegalArgumentException
(assertions/called-at-least-once-with-args? target/foo [])))))

View file

@ -0,0 +1,109 @@
(ns bond.james-test
{:clj-kondo/config {:linters {:private-call {:level :off}
:invalid-arity {:level :off}}}}
(:require [clojure.test :refer (deftest is testing)]
[bond.james :as bond :include-macros true]
[bond.target-data :as target]))
(deftest spy-logs-args-and-results
(bond/with-spy [target/foo]
(is (= 2 (target/foo 1)))
(is (= 4 (target/foo 2)))
(is (= [{:args [1] :return 2}
{:args [2] :return 4}]
(bond/calls target/foo)))
(let [exception (is (thrown? clojure.lang.ArityException (target/foo 3 4)))]
(is (= {:args [3 4] :throw exception}
(-> target/foo bond/calls last))))))
(deftest calls-fails-on-unspied-fns
(is (thrown? IllegalArgumentException
(bond/calls target/foo))))
(deftest spy-can-spy-private-fns
(bond/with-spy [target/private-foo]
(is (= 4 (#'target/private-foo 2)))
(is (= 6 (#'target/private-foo 3)))
(is (= [{:args [2] :return 4}
{:args [3] :return 6}]
(bond/calls #'target/private-foo)))))
(deftest stub-works
(is (= ""
(with-out-str
(bond/with-stub [target/bar]
(target/bar 3))))))
(deftest stub-works-with-private-fn
(testing "without replacement"
(bond/with-stub [target/private-foo]
(is (nil? (#'target/private-foo 3)))
(is (= [3] (-> #'target/private-foo bond/calls first :args)))))
(testing "with replacement"
(bond/with-stub [[target/private-foo (fn [x] (* x x))]]
(is (= 9 (#'target/private-foo 3)))
(is (= [3] (-> #'target/private-foo bond/calls first :args))))))
(deftest stub-with-replacement-works
(bond/with-stub [target/foo
[target/bar #(str "arg is " %)]]
(testing "stubbing works"
(is (nil? (target/foo 4)))
(is (= "arg is 3" (target/bar 3))))
(testing "spying works"
(is (= [4] (-> target/foo bond/calls first :args)))
(is (= [3] (-> target/bar bond/calls first :args))))))
(deftest iterator-style-stubbing-works
(bond/with-stub [target/foo
[target/bar [#(str "first arg is " %)
#(str "second arg is " %)
#(str "third arg is " %)]]]
(testing "stubbing works"
(is (nil? (target/foo 4)))
(is (= "first arg is 3" (target/bar 3)))
(is (= "second arg is 4" (target/bar 4)))
(is (= "third arg is 5" (target/bar 5))))
(testing "spying works"
(is (= [4] (-> target/foo bond/calls first :args)))
(is (= [3] (-> target/bar bond/calls first :args)))
(is (= [4] (-> target/bar bond/calls second :args)))
(is (= [5] (-> target/bar bond/calls last :args))))))
(deftest stub!-complains-loudly-if-there-is-no-arglists
(is (thrown? IllegalArgumentException
(bond/with-stub! [[target/without-arglists (constantly 42)]]
(throw (Exception. "shouldn't get here"))))))
(deftest stub!-throws-arity-exception
(bond/with-stub! [[target/foo (constantly 9)]]
(is (= 9 (target/foo 12)))
(is (= [{:args [12] :return 9}] (bond/calls target/foo))))
(bond/with-stub! [target/bar
target/quuk
[target/quux (fn [_ _ & x] x)]]
(is (thrown? clojure.lang.ArityException
(target/bar 1 2)))
(is (thrown? clojure.lang.ArityException
(target/quuk 1)))
(is (= [6 5] (target/quux 8 7 6 5)))))
(deftest spying-entire-namespaces-works
(bond/with-spy-ns [bond.target-data]
(target/foo 1)
(target/foo 2)
(is (= [{:args [1] :return 2}
{:args [2] :return 4}]
(bond/calls target/foo)))
(is (= 0 (-> target/bar bond/calls count)))))
(deftest stubbing-entire-namespaces-works
(testing "without replacements"
(bond/with-stub-ns [bond.target-data]
(is (nil? (target/foo 10)))
(is (= [10] (-> target/foo bond/calls first :args)))))
(testing "with replacements"
(bond/with-stub-ns [[bond.target-data (constantly 3)]]
(is (= 3 (target/foo 10)))
(is (= [10] (-> target/foo bond/calls first :args))))))

View file

@ -0,0 +1,35 @@
(ns bond.target-data
"Reference def targets for bond to test against."
{:clj-kondo/config {:linters {:unused-binding {:level :off}
:unused-private-var {:level :off}}}})
(defn foo
[x]
(* 2 x))
(defn- private-foo
[x]
(* 2 x))
(defn foo-caller [x]
(foo x))
(defn bar
[x]
(println "bar!") (* 2 x))
(defn quux
[a b & c]
c)
(defn quuk
[a b & c]
c)
(defmacro baz
[x]
`(* ~x 2))
(def without-arglists
(fn [x]
(* 2 x)))

View file

@ -0,0 +1,20 @@
(ns borkdude.deps.smoke-test
(:require [clojure.test :as t :refer [deftest is]]
[clojure.java.io :as io]
[clojure.string :as str]
[babashka.curl :as curl]))
(def windows? (-> (System/getProperty "os.name")
(str/lower-case)
(str/includes? "win")))
(deftest basic-test
(spit "deps_test.clj"
(:body (curl/get "https://raw.githubusercontent.com/borkdude/deps.clj/master/deps.clj"
(if windows? {:compressed false} {}))))
(binding [*command-line-args* ["-Sdescribe"]]
(load-file "deps_test.clj"))
(.delete (io/file "deps_test.clj")))

View file

@ -0,0 +1,133 @@
(ns borkdude.rewrite-edn-test
(:require [borkdude.rewrite-edn :as r]
[clojure.test :as t :refer [deftest testing is]]))
(deftest assoc-test
(testing "Base case"
(is (= "{:a 1}"
(str (r/assoc
(r/parse-string "{}")
:a 1)))))
(testing "When there's only one existing, keys are added on a new line"
(is (= "
{:a 1
:b 1}"
(str (r/assoc
(r/parse-string "
{:a 1}")
:b 1)))))
(testing "Unless there are already keys on the same line"
(is (= "{:a 1 :b 2 :c 3}"
(str (r/assoc
(r/parse-string "{:a 1 :b 2}")
:c 3)))))
(testing "when map is already multi-line, new keys are added on new line"
(is (= "
{:a 1
:b 2}
;; this is a cool map"
(str (r/assoc
(r/parse-string "
{:a 1}
;; this is a cool map")
:b 2)))))
(testing "Updating existing val"
(is (= "{:a 2}"
(str (r/assoc
(r/parse-string "{:a 1}")
:a 2)))))
(testing "Something between key and val"
(is (= "{:a #_:something 2}"
(str (r/assoc
(r/parse-string "{:a #_:something 1}")
:a 2)))))
(testing "Comment at the end"
(is (= "{:a 2} ;; this is a cool map"
(str (r/assoc
(r/parse-string "{:a 1} ;; this is a cool map")
:a 2)))))
(testing "Vector index assoc"
(is (= "[9 8 99 7] ;; this is a cool vector"
(str (r/assoc
(r/parse-string "[9 8 3 7] ;; this is a cool vector")
2 99)))))
(testing "Vector last index assoc"
(is (= "[9 8 3 99] ;; this is a cool vector"
(str (r/assoc
(r/parse-string "[9 8 3 7] ;; this is a cool vector")
3 99)))))
(testing "Vector assoc out of bounds"
(is (try
(r/assoc (r/parse-string "[9 8 3 7] ;; this is a cool vector") 9 99)
false
(catch java.lang.IndexOutOfBoundsException _ true))))
(testing "Vector assoc out of bounds with ignored"
(is (try
(r/assoc (r/parse-string "[9 8 3 #_99 #_213 7] ;; this is a cool vector") 4 99)
false
(catch java.lang.IndexOutOfBoundsException _ true)))))
(deftest update-test
(is (= "{:a #_:foo 2}"
(str (r/update
(r/parse-string "{:a #_:foo 1}")
:a (fn [node]
(inc (r/sexpr node))))))))
(defn qualify-sym-node [sym-node]
(let [sym (r/sexpr sym-node)]
(if (or (not (symbol? sym))
(qualified-symbol? sym))
sym-node
(symbol (str sym) (str sym)))))
(deftest map-keys-test
(is (= "
{foo/foo 1
bar/bar 2}"
(str (r/map-keys qualify-sym-node
(r/parse-string "
{foo 1
bar 2}"))))))
(deftest update-deps-test
(is (= "{:deps {foo/foo {:mvn/version \"0.1.0\"}}}"
(str (r/update (r/parse-string "{:deps {foo {:mvn/version \"0.1.0\"}}}")
:deps
(fn [deps-map-node]
(r/map-keys qualify-sym-node deps-map-node)))))))
(deftest assoc-in-test
(is (= "{:a {:b {:c 2}}}"
(str (r/assoc-in (r/parse-string "{}")
[:a :b :c] 2))))
(is (= "{:a {:b {:c 2}}}"
(str (r/assoc-in (r/parse-string "nil")
[:a :b :c] 2))))
(is (= "{:deps {foo/foo {:mvn/version \"0.2.0\"}}}"
(str (r/assoc-in (r/parse-string "{:deps {foo/foo {:mvn/version \"0.1.0\"}}}")
[:deps 'foo/foo :mvn/version]
"0.2.0"))))
(is (= "{:a 1 :b {:c 1}}"
(str (r/assoc-in (r/parse-string "{:a 1}") [:b :c] 1)))))
(deftest update-in-test
(is (= "{:deps {foo/foo {:mvn/version \"0.2.0\"}}}"
(str (r/update-in (r/parse-string "{:deps {foo/foo {:mvn/version \"0.1.0\"}}}")
[:deps 'foo/foo]
#(r/assoc % :mvn/version "0.2.0")))))
(is (= "{:a {:b {:c 1}}}"
(str (r/update-in (r/parse-string "{}")
[:a :b :c]
(comp (fnil inc 0) r/sexpr)))))
(is (= "{:a {:b {:c 1}}}"
(str (r/update-in (r/parse-string "nil")
[:a :b :c]
(comp (fnil inc 0) r/sexpr))))))
(deftest dissoc-test
(is (= "{}" (str (r/dissoc (r/parse-string "{:a 1}") :a))))
(is (= "{:a 1}" (str (r/dissoc (r/parse-string "{:a 1 \n\n:b 2}") :b))))
(is (= "{:a 1\n:c 3}" (str (r/dissoc (r/parse-string "{:a 1\n:b 2\n:c 3}") :b))))
(is (= "{:deps {foo/bar {}}}" (str (r/update (r/parse-string "{:deps {foo/bar {} foo/baz {}}}")
:deps #(r/dissoc % 'foo/baz))))))

View file

@ -47,7 +47,11 @@
(testing "handling of blank input string"
(is (= "" (csk/->kebab-case "")))
(is (= "" (csk/->kebab-case " ")))))
(is (= "" (csk/->kebab-case " "))))
(testing "handling of input consisting of only separator(s)"
(is (= "" (csk/->kebab-case "a" :separator \a)))
(is (= "" (csk/->kebab-case "aa" :separator \a)))))
(deftest http-header-case-test
(are [x y] (= x (csk/->HTTP-Header-Case y))

View file

@ -0,0 +1,16 @@
(ns camel-snake-kebab.extras-test
(:require [camel-snake-kebab.core :as csk]
[camel-snake-kebab.extras :refer [transform-keys]]
#?(:clj [clojure.test :refer :all]
:cljs [cljs.test :refer-macros [deftest testing is are]])))
(deftest transform-keys-test
(are [x y] (= x (transform-keys csk/->kebab-case-keyword y))
nil nil
{} {}
[] []
{:total-books 0 :all-books []} {'total_books 0 "allBooks" []}
[{:the-author "Dr. Seuss" :the-title "Green Eggs and Ham"}]
[{'the-Author "Dr. Seuss" "The_Title" "Green Eggs and Ham"}]
{:total-books 1 :all-books [{:the-author "Dr. Seuss" :the-title "Green Eggs and Ham"}]}
{'total_books 1 "allBooks" [{'THE_AUTHOR "Dr. Seuss" "the_Title" "Green Eggs and Ham"}]}))

View file

@ -0,0 +1,41 @@
(ns camel-snake-kebab.internals.string-separator-test
(:require [camel-snake-kebab.internals.string-separator :refer [split generic-separator]]
#?(:clj [clojure.test :refer :all]
:cljs [cljs.test :refer-macros [deftest testing is are]])))
(deftest split-test
(testing "regex, string and character separators"
(are [sep]
(and (= ["foo" "bar"] (split sep "foo.bar"))
(= [""] (split sep "")))
#"\." "." \.))
(testing "input consisting of separator(s)"
(is (empty? (split "x" "x")))
(is (empty? (split "x" "xx"))))
(testing "generic separator"
(are [x y]
(= x (split generic-separator y))
[""] ""
[""] " "
["x"] " x "
["foo" "bar"] "foo bar"
["foo" "bar"] "foo\n\tbar"
["foo" "bar"] "foo-bar"
["foo" "Bar"] "fooBar"
["Foo" "Bar"] "FooBar"
["foo" "bar"] "foo_bar"
["FOO" "BAR"] "FOO_BAR"
["räksmörgås"] "räksmörgås"
["IP" "Address"] "IPAddress"
["Adler" "32"] "Adler32"
["Inet" "4" "Address"] "Inet4Address"
["Arc" "2" "D"] "Arc2D"
["a" "123b"] "a123b"
["A" "123" "B"] "A123B")))

View file

@ -0,0 +1,10 @@
(ns camel-snake-kebab.test-runner
(:require [cljs.test :as test]
[doo.runner :refer-macros [doo-all-tests doo-tests]]
[camel-snake-kebab.core-test]
[camel-snake-kebab.extras-test]
[camel-snake-kebab.internals.string-separator-test]))
(doo-tests 'camel-snake-kebab.core-test
'camel-snake-kebab.extras-test
'camel-snake-kebab.internals.string-separator-test)

View file

@ -24,11 +24,12 @@
:accept :json
:throw-exceptions false})))))
(deftest insecure-test
(is (= 200 (:status (client/get "https://self-signed.badssl.com/" {:insecure? true})))))
(deftest exception-test
(try (client/get "https://site.com/broken")
(is false "should not reach here")
(catch Exception e
(is (:headers (ex-data e))))))
;; BB-TEST-PATCH: Added test
(deftest insecure-test
(is (= 200 (:status (client/get "https://self-signed.badssl.com/" {:insecure? true})))))

View file

@ -0,0 +1,10 @@
(ns clj-http.lite.test-runner
(:require [clj-http.lite.client-test]
[clojure.test :as t]))
(defn -main [& _]
(let [{:keys [fail error]} (t/run-tests 'clj-http.lite.client-test)]
(System/exit (if (or (pos? fail)
(pos? error))
1 0))))

View file

@ -0,0 +1,83 @@
(ns clj-stacktrace.core-test
(:use clojure.test)
(:use clj-stacktrace.core)
(:use clj-stacktrace.utils))
(def cases
[["foo.bar$biz__123" "invoke" "bar.clj" 456
{:clojure true :ns "foo.bar" :fn "biz"
:file "bar.clj" :line 456 :anon-fn false}]
["foo.bar$biz_bat__123" "invoke" "bar.clj" 456
{:clojure true :ns "foo.bar" :fn "biz-bat"
:file "bar.clj" :line 456 :anon-fn false}]
["foo.bar$biz_bat_QMARK___448" "invoke" "bar.clj" 456
{:clojure true :ns "foo.bar" :fn "biz-bat?"
:file "bar.clj" :line 456 :anon-fn false}]
["foo.bar$biz_bat_QMARK___448$fn__456" "invoke" "bar.clj" 456
{:clojure true :ns "foo.bar" :fn "biz-bat?"
:file "bar.clj" :line 456 :anon-fn true}]
["foo.bar$repl$fn__5629.invoke" "invoke" "bar.clj" 456
{:clojure true :ns "foo.bar" :fn "repl"
:file "bar.clj" :line 456 :anon-fn true}]
["foo.bar$repl$read_eval_print__5624" "invoke" "bar.clj" 456
{:clojure true :ns "foo.bar" :fn "repl"
:file "bar.clj" :line 456 :anon-fn true}]
["foo.bar$biz__123$fn__456" "invoke" "bar.clj" 789
{:clojure true :ns "foo.bar" :fn "biz"
:file "bar.clj" :line 789 :anon-fn true}]
["foo.bar_bat$biz__123" "invoke" "bar.clj" 456
{:clojure true :ns "foo.bar-bat" :fn "biz"
:file "bar.clj" :line 456 :anon-fn false}]
["user$eval__345" "invoke" nil -1
{:clojure true :ns "user" :fn "eval"
:file nil :line nil :anon-fn false}]
["lamina.core.observable.ConstantObservable" "message" "observable.clj" 198
{:clojure true :ns "lamina.core.observable"
:fn "lamina.core.observable.ConstantObservable"
:file "observable.clj" :line 198 :anon-fn false}]
["clojure.lang.Var" "invoke" "Var.java" 123
{:java true :class "clojure.lang.Var" :method "invoke"
:file "Var.java" :line 123}]
["clojure.proxy.space.SomeClass" "someMethod" "SomeClass.java" 123
{:java true :class "clojure.proxy.space.SomeClass" :method "someMethod"
:file "SomeClass.java" :line 123}]
["some.space.SomeClass" "someMethod" "SomeClass.java" 123
{:java true :class "some.space.SomeClass" :method "someMethod"
:file "SomeClass.java" :line 123}]
["some.space.SomeClass$SomeInner" "someMethod" "SomeClass.java" 123
{:java true :class "some.space.SomeClass$SomeInner" :method "someMethod"
:file "SomeClass.java" :line 123}]
["some.space.SomeClass" "someMethod" nil -1
{:java true :class "some.space.SomeClass" :method "someMethod"
:file nil :line nil}]])
(deftest test-parse-trace-elem
(doseq [[class method file line parsed] cases
:let [elem (StackTraceElement. class method file line)]]
(is (= parsed (parse-trace-elem elem)))))
(deftest test-trim-redundant
(let [trim-fn (resolve 'clj-stacktrace.core/trim-redundant)]
(is (= '(d c) (trim-fn '(d c b a) '(f e b a))))
(is (= '(c) (trim-fn '(c b a) '(f e b a))))
(is (= '(d c) (trim-fn '(d c b a) '(e b a))))))
(deftest test-parse-exception
(try
(eval '(/))
(catch Exception e
(is (parse-exception e)))))

View file

@ -0,0 +1,31 @@
(ns clj-stacktrace.repl-test
(:use clojure.test)
(:use clj-stacktrace.utils)
(:use clj-stacktrace.repl))
(defmacro with-cascading-exception
"Execute body in the context of a variable bound to an exception instance
that includes a caused-by cascade."
[binding-sym & body]
`(try (first (lazy-seq (cons (/) nil)))
(catch Exception e#
(let [~binding-sym e#]
~@body))))
(deftest test-pst
(with-cascading-exception e
(is (with-out-str (pst e)))
(binding [*e e]
(is (with-out-str (pst))))))
(deftest test-pst-str
(with-cascading-exception e
(is (pst-str e))
(binding [*e e]
(is (pst-str)))))
(deftest test-pst+
(with-cascading-exception e
(is (with-out-str (pst+ e)))
(binding [*e e]
(is (with-out-str (pst+))))))

View file

@ -1,8 +1,15 @@
(ns clj-yaml.core-test
(:require [clojure.test :refer (deftest testing is)]
[clojure.string :as string]
[clj-yaml.core :refer [parse-string unmark generate-string]])
(:import [java.util Date]))
[clojure.java.io :as io]
[clj-yaml.core :refer [parse-string unmark generate-string
parse-stream generate-stream]])
(:import [java.util Date]
(java.io ByteArrayOutputStream OutputStreamWriter ByteArrayInputStream)
java.nio.charset.StandardCharsets
(org.yaml.snakeyaml.error YAMLException)
;; BB-TEST-PATCH: bb doesn't have these classes
#_(org.yaml.snakeyaml.constructor DuplicateKeyException)))
(def nested-hash-yaml
"root:\n childa: a\n childb: \n grandchild: \n greatgrandchild: bar\n")
@ -27,7 +34,7 @@ items:
")
(def inline-list-yaml
"--- # Shopping list
"--- # Shopping list
[milk, pumpkin pie, eggs, juice]
")
@ -160,8 +167,8 @@ the-bin: !!binary 0101")
;; This test ensures that generate-string uses the older behavior by default, for the sake
;; of stability, i.e. backwards compatibility.
(is
(= "{description: Big-picture diagram showing how our top-level systems and stakeholders interact}\n"
(generate-string data))))))
(= "{description: Big-picture diagram showing how our top-level systems and stakeholders interact}\n"
(generate-string data))))))
(deftest dump-opts
(let [data [{:age 33 :name "jon"} {:age 44 :name "boo"}]]
@ -170,9 +177,7 @@ the-bin: !!binary 0101")
(is (= "[{age: 33, name: jon}, {age: 44, name: boo}]\n"
(generate-string data :dumper-options {:flow-style :flow})))))
;; TODO: this test is failing in GraalVM
;; Could be related to https://github.com/oracle/graal/issues/2234
#_(deftest parse-time
(deftest parse-time
(testing "clj-time parses timestamps with more than millisecond precision correctly."
(let [timestamp "2001-11-23 15:02:31.123456 -04:00"
expected 1006542151123]
@ -182,7 +187,7 @@ the-bin: !!binary 0101")
(let [parsed (parse-string hashes-lists-yaml)
[first second] (:items parsed)]
(is (= (keys first) '(:part_no :descrip :price :quantity)))
(is (= (keys second)'(:part_no :descrip :price :quantity :owners)))))
(is (= (keys second) '(:part_no :descrip :price :quantity :owners)))))
(deftest nulls-are-fine
@ -201,3 +206,90 @@ the-bin: !!binary 0101")
(testing "emoji in comments are OK too"
(let [yaml "# 💣 emoji in a comment\n42"]
(is (= 42 (parse-string yaml))))))
(def too-many-aliases
(->> (range 51)
(map #(str "b" % ": *a"))
(cons "a: &a [\"a\",\"a\"]")
(string/join "\n")))
(deftest max-aliases-for-collections-works
(is (thrown-with-msg? YAMLException #"Number of aliases" (parse-string too-many-aliases)))
(is (parse-string too-many-aliases :max-aliases-for-collections 51)))
(def recursive-yaml "
---
&A
- *A: *A
")
(deftest allow-recursive-works
(is (thrown-with-msg? YAMLException #"Recursive" (parse-string recursive-yaml)))
(is (parse-string recursive-yaml :allow-recursive-keys true)))
(def duplicate-keys-yaml "
a: 1
a: 1
")
#_(deftest duplicate-keys-works
(is (parse-string duplicate-keys-yaml))
(is (thrown-with-msg? DuplicateKeyException #"found duplicate key" (parse-string duplicate-keys-yaml :allow-duplicate-keys false))))
(def namespaced-keys-yaml "
foo/bar: 42
")
(deftest namespaced-keys-works
(testing "namespaced keys in yaml can round trip through parse and generate"
(is (= {:foo/bar 42} (-> namespaced-keys-yaml
parse-string
generate-string
parse-string)))))
(defn to-bytes
"Converts a string to a byte array."
[data]
(.getBytes ^String data StandardCharsets/UTF_8))
(defn roundtrip
"Testing roundtrip of string and stream parser, and checking their equivalence."
[data-as-string]
(let [data (parse-string data-as-string)
data-stream (parse-stream (io/reader (ByteArrayInputStream. (to-bytes data-as-string))))
output-stream (ByteArrayOutputStream.)
writer (OutputStreamWriter. output-stream)
_ (generate-stream writer data)
reader (ByteArrayInputStream. (.toByteArray output-stream))]
(= data ;; string -> edn
(parse-string (generate-string data)) ;; edn -> string -> edn
(parse-stream (io/reader reader)) ;; edn -> stream -> edn
;; stream -> edn
data-stream)))
(deftest roundtrip-test
(testing "Roundtrip test"
(is (roundtrip duplicate-keys-yaml))
(is (roundtrip hashes-of-lists-yaml))
(is (roundtrip inline-hash-yaml))
(is (roundtrip inline-list-yaml))
(is (roundtrip list-of-hashes-yaml))
(is (roundtrip list-yaml))
(is (roundtrip nested-hash-yaml))))
(def indented-yaml "todo:
- name: Fix issue
responsible:
name: Rita
")
;; BB-TEST-PATCH - bb generates different indents
#_(deftest indentation-test
(testing "Can use indicator-indent and indent to achieve desired indentation"
(is (not= indented-yaml (generate-string (parse-string indented-yaml)
:dumper-options {:flow-style :block})))
(is (= indented-yaml
(generate-string (parse-string indented-yaml)
:dumper-options {:indent 5
:indicator-indent 2
:flow-style :block})))))

View file

@ -0,0 +1,229 @@
;; Test routines for clojure.algo.monads
;; Copyright (c) Konrad Hinsen, 2011. All rights reserved. The use
;; and distribution terms for this software are covered by the Eclipse
;; Public License 1.0 (http://opensource.org/licenses/eclipse-1.0.php)
;; which can be found in the file epl-v10.html at the root of this
;; distribution. By using this software in any fashion, you are
;; agreeing to be bound by the terms of this license. You must not
;; remove this notice, or any other, from this software.
(ns clojure.algo.test-monads
(:use [clojure.test :only (deftest is are run-tests)]
[clojure.algo.monads
:only (with-monad domonad m-lift m-seq m-chain writer-m write
sequence-m maybe-m state-m maybe-t sequence-t
reader-m ask asks local)]))
(deftest domonad-if-then
(let [monad-value (domonad maybe-m
[ a 5
:let [c 7]
:if (and (= a 5) (= c 7))
:then [
b 6
]
:else [
b nil
]]
[a b])]
(is (= monad-value [5 6]))))
(deftest domonad-nested-if-then
(let [monad-value (domonad maybe-m
[ a 5
:if (= a 5)
:then [
b 6
:if (= b 6)
:then [
c 7
]
:else [
c nil
]
]
:else [
b nil
c nil
]]
[a b c])]
(is (= monad-value [5 6 7]))))
(deftest domonad-if-then-with-when
(let [monad-value (domonad maybe-m
[ a 5
:when (= a 5)
:if (= a 1)
:then [
b 6]
:else [
b nil]]
[a b])]
(is (= monad-value nil))))
(deftest domonad-cond
(let [monad-value (domonad maybe-m
[ a 5
:when (= a 5)
:cond
[(< a 1)
[result "less than one"]
(< a 3)
[result "less than three"]
(< a 6)
[result "less than six"]
:else
[result "arbitrary number"]]
b 7
:let [some-val 12345]]
[result b some-val])]
(is (= monad-value ["less than six" 7 12345]))))
(deftest sequence-monad
(with-monad sequence-m
(are [a b] (= a b)
(domonad [x (range 3) y (range 2)] (+ x y))
'(0 1 1 2 2 3)
(domonad [x (range 5) y (range (+ 1 x)) :when (= (+ x y) 2)] (list x y))
'((1 1) (2 0))
((m-lift 2 #(list %1 %2)) (range 3) (range 2))
'((0 0) (0 1) (1 0) (1 1) (2 0) (2 1))
(m-seq (repeat 3 (range 2)))
'((0 0 0) (0 0 1) (0 1 0) (0 1 1) (1 0 0) (1 0 1) (1 1 0) (1 1 1))
((m-chain (repeat 3 range)) 5)
'(0 0 0 1 0 0 1 0 1 2)
(m-plus (range 3) (range 2))
'(0 1 2 0 1))))
(deftest maybe-monad
(with-monad maybe-m
(let [m+ (m-lift 2 +)
mdiv (fn [x y] (domonad [a x b y :when (not (zero? b))] (/ a b)))]
(are [a b] (= a b)
(m+ (m-result 1) (m-result 3))
(m-result 4)
(mdiv (m-result 1) (m-result 3))
(m-result (/ 1 3))
(m+ 1 (mdiv (m-result 1) (m-result 0)))
m-zero
(m-plus m-zero (m-result 1) m-zero (m-result 2))
(m-result 1)))))
(deftest writer-monad
(is (= (domonad (writer-m "")
[x (m-result 1)
_ (write "first step\n")
y (m-result 2)
_ (write "second step\n")]
(+ x y))
[3 "first step\nsecond step\n"]))
(is (= (domonad (writer-m [])
[_ (write :a)
a (m-result 1)
_ (write :b)
b (m-result 2)]
(+ a b))
[3 [:a :b]]))
(is (= (domonad (writer-m ())
[_ (write :a)
a (m-result 1)
_ (write :b)
b (m-result 2)]
(+ a b))
[3 '(:a :b)]))
(is (= (domonad (writer-m (list))
[_ (write :a)
a (m-result 1)
_ (write :b)
b (m-result 2)]
(+ a b))
[3 (list :a :b)]))
(is (= (domonad (writer-m #{})
[_ (write :a)
a (m-result 1)
_ (write :a)
b (m-result 2)]
(+ a b))
[3 #{:a}]))
(is (= (domonad (writer-m ())
[_ (domonad
[_ (write "foo")]
nil)
_ (write "bar")]
1)
[1 '("foo" "bar")])))
(deftest reader-monad
(let [monad-value (domonad reader-m
[x (asks :number)]
(* x 2))]
(is (= (monad-value {:number 3})
6)))
(let [monad-value (domonad reader-m
[env (ask)]
env)]
(is (= (monad-value "env")
"env")))
(let [monad-value (domonad reader-m
[numbers (ask)
sum (m-result (reduce + numbers))
mean (m-result (/ sum (count numbers)))]
mean)]
(is (= (monad-value (range 1 10))
5)))
(let [monad-value (domonad reader-m
[a (ask)
b (local inc (ask))]
(* a b))]
(is (= (monad-value 10)
110)))
(let [mult-a-b (fn []
(domonad reader-m
[a (asks :a)
b (asks :b)]
(* a b)))
monad-value (domonad reader-m
[a (asks :a)
b (asks :b)
a* (local #(update-in % [:a] inc) (asks :a))
c (local #(assoc % :b 5) (mult-a-b))]
[a b a* c])]
(= (monad-value {:a 10})
[10 nil 11 50])))
(deftest seq-maybe-monad
(with-monad (maybe-t sequence-m)
(letfn [(pairs [xs] ((m-lift 2 #(list %1 %2)) xs xs))]
(are [a b] (= a b)
((m-lift 1 inc) (for [n (range 10)] (when (odd? n) n)))
'(nil 2 nil 4 nil 6 nil 8 nil 10)
(pairs (for [n (range 5)] (when (odd? n) n)))
'(nil nil (1 1) nil (1 3) nil nil nil (3 1) nil (3 3) nil nil)))))
(deftest state-maybe-monad
(with-monad (maybe-t state-m)
(is (= (for [[a b c d] (list [1 2 3 4] [nil 2 3 4] [ 1 nil 3 4]
[nil nil 3 4] [1 2 nil nil])]
(let [f (domonad
[x (m-plus (m-result a) (m-result b))
y (m-plus (m-result c) (m-result d))]
(+ x y))]
(f :state)))
(list [4 :state] [5 :state] [4 :state] [nil :state] [nil :state])))))
(deftest state-seq-monad
(with-monad (sequence-t state-m)
(is (= (let [[a b c d] [1 2 10 20]
f (domonad
[x (m-plus (m-result a) (m-result b))
y (m-plus (m-result c) (m-result d))]
(+ x y))]
(f :state)))
(list [(list 11 21 12 22) :state]))))

View file

@ -32,4 +32,4 @@
(gen/reservoir-sample 10 coll))
sample-2 (binding [gen/*rnd* (java.util.Random. n)]
(gen/reservoir-sample 10 coll))]
(is (= sample-1 sample-2)))))
(is (= sample-1 sample-2)))))

View file

@ -414,7 +414,8 @@
(is (= x (json/read-str (with-out-str (json/pprint x)))))))
(deftest pretty-print-nonescaped-unicode
(is (= "\"\u1234\u4567\"\n"
;; BB-TEST-PATCH: Windows compatability
(is (= (str "\"\u1234\u4567\"" (System/lineSeparator))
(with-out-str
(json/pprint "\u1234\u4567" :escape-unicode false)))))

View file

@ -0,0 +1,17 @@
(ns clojure.data.zip-test
(:require [clojure.test :as t :refer [deftest is]]
[clojure.data.xml :as xml]
[clojure.zip :as zip]
[clojure.data.zip.xml :refer [attr attr= xml1->]]))
(def data (str "<root>"
" <character type=\"person\" name=\"alice\" />"
" <character type=\"animal\" name=\"march hare\" />"
"</root>"))
(deftest xml1-test
(let [xml (zip/xml-zip (xml/parse (java.io.StringReader. data)))]
(is (= "person"
(xml1-> xml :character [(attr= :name "alice")] (attr :type))))
(is (= "march hare"
(xml1-> xml :character [(attr= :type "animal")] (attr :name))))))

View file

@ -0,0 +1,29 @@
(ns clojure.term.colors-test
(:require [clojure.test :refer :all]
[clojure.term.colors :refer :all]))
(defn get-fn
"get function from symbol in clojure.term.colors package"
[fname]
(ns-resolve (the-ns 'clojure.term.colors)
(-> fname name symbol)))
(defn test-colors-from-map
"test print colors from a color map"
[colormap & more]
(eval
`(do ~@(map (fn [[color _]]
`(println ((get-fn ~color)
(name ~color) (str ~@more))))
colormap))))
(deftest color-test
(testing "Testing colors."
(test-colors-from-map *colors* " foreground.")
(test-colors-from-map *highlights* " background.")
(test-colors-from-map *attributes* " attributes."))
(testing "Testing disable colors."
(binding [*disable-colors* true]
(println \newline "When disabled-colors is set ...")
(test-colors-from-map *colors* " foreground."))))

View file

@ -95,6 +95,7 @@
(is (thrown-with-msg? clojure.lang.ExceptionInfo #"did not conform to spec" (no-kwargs-fn 1 :not-num)))
(is (thrown-with-msg? clojure.lang.ExceptionInfo #"did not conform to spec" (no-kwargs-fn 1 2 :not-num 3)))
;; BB-TEST-PATCH: bb gets sci internals instead
#_(testing "that the ex-info data looks correct"
(try (fail-no-kwargs 1 :not-num)
(catch Exception ei
@ -151,14 +152,15 @@
(is (thrown-with-msg? clojure.lang.ExceptionInfo #"did not conform to spec" (kwargs-fn 1 :not-num)))
(is (thrown-with-msg? clojure.lang.ExceptionInfo #"did not conform to spec" (kwargs-fn 1 2 :a 1 {:b :not-num})))
;; BB-TEST-PATCH: bb gets sci internals instead
#_(testing "that the ex-info data looks correct"
(try (fail-kwargs 1 :not-num)
(catch Exception ei
(is (= 'clojure.test-clojure.instr/fail-kwargs (-> ei ex-data :clojure.spec.test.alpha/caller :var-scope)))))
(try (fail-kwargs 1 :not-num)
(catch Exception ei
(is (= 'clojure.test-clojure.instr/fail-kwargs (-> ei ex-data :clojure.spec.test.alpha/caller :var-scope)))))
(try (fail-kwargs 1 2 :a 1 {:b :not-num})
(catch Exception ei
(is (= 'clojure.test-clojure.instr/fail-kwargs (-> ei ex-data :clojure.spec.test.alpha/caller :var-scope)))))))
(try (fail-kwargs 1 2 :a 1 {:b :not-num})
(catch Exception ei
(is (= 'clojure.test-clojure.instr/fail-kwargs (-> ei ex-data :clojure.spec.test.alpha/caller :var-scope)))))))
(testing "that the uninstrumented kwargs function operates as the raw function"
(stest/unstrument `kwargs-fn)

View file

@ -1,11 +1,3 @@
; Copyright (c) Rich Hickey. All rights reserved.
; The use and distribution terms for this software are covered by the
; Eclipse Public License 1.0 (http://opensource.org/licenses/eclipse-1.0.php)
; which can be found in the file epl-v10.html at the root of this distribution.
; By using this software in any fashion, you are agreeing to be bound by
; the terms of this license.
; You must not remove this notice, or any other, from this software.
(ns clojure.test-clojure.spec
(:require [clojure.spec.alpha :as s]
[clojure.spec.gen.alpha :as gen]
@ -167,6 +159,7 @@
(is (= (s/describe odd?) 'odd?))
(is (= (s/form odd?) 'clojure.core/odd?))
;; BB-TEST-PATCH: Returns sci internal
#_(is (= (s/describe #(odd? %)) ::s/unknown))
#_(is (= (s/form #(odd? %)) ::s/unknown)))

View file

@ -0,0 +1,315 @@
(ns clojure.tools.namespace.dependency-test
(:use clojure.test
clojure.tools.namespace.dependency))
;; building a graph like:
;;
;; :a
;; / |
;; :b |
;; \ |
;; :c
;; |
;; :d
;;
(def g1 (-> (graph)
(depend :b :a) ; "B depends on A"
(depend :c :b) ; "C depends on B"
(depend :c :a) ; "C depends on A"
(depend :d :c))) ; "D depends on C"
;; 'one 'five
;; | |
;; 'two |
;; / \ |
;; / \ |
;; / \ /
;; 'three 'four
;; | /
;; 'six /
;; | /
;; | /
;; | /
;; 'seven
;;
(def g2 (-> (graph)
(depend 'two 'one)
(depend 'three 'two)
(depend 'four 'two)
(depend 'four 'five)
(depend 'six 'three)
(depend 'seven 'six)
(depend 'seven 'four)))
;; :level0
;; / | | \
;; ----- | | -----
;; / | | \
;; :level1a :level1b :level1c :level1d
;; \ | | /
;; ----- | | -----
;; \ | | /
;; :level2
;; / | | \
;; ----- | | -----
;; / | | \
;; :level3a :level3b :level3c :level3d
;; \ | | /
;; ----- | | -----
;; \ | | /
;; :level4
;;
;; ... and so on in a repeating pattern like that, up to :level26
(def g3 (-> (graph)
(depend :level1a :level0)
(depend :level1b :level0)
(depend :level1c :level0)
(depend :level1d :level0)
(depend :level2 :level1a)
(depend :level2 :level1b)
(depend :level2 :level1c)
(depend :level2 :level1d)
(depend :level3a :level2)
(depend :level3b :level2)
(depend :level3c :level2)
(depend :level3d :level2)
(depend :level4 :level3a)
(depend :level4 :level3b)
(depend :level4 :level3c)
(depend :level4 :level3d)
(depend :level5a :level4)
(depend :level5b :level4)
(depend :level5c :level4)
(depend :level5d :level4)
(depend :level6 :level5a)
(depend :level6 :level5b)
(depend :level6 :level5c)
(depend :level6 :level5d)
(depend :level7a :level6)
(depend :level7b :level6)
(depend :level7c :level6)
(depend :level7d :level6)
(depend :level8 :level7a)
(depend :level8 :level7b)
(depend :level8 :level7c)
(depend :level8 :level7d)
(depend :level9a :level8)
(depend :level9b :level8)
(depend :level9c :level8)
(depend :level9d :level8)
(depend :level10 :level9a)
(depend :level10 :level9b)
(depend :level10 :level9c)
(depend :level10 :level9d)
(depend :level11a :level10)
(depend :level11b :level10)
(depend :level11c :level10)
(depend :level11d :level10)
(depend :level12 :level11a)
(depend :level12 :level11b)
(depend :level12 :level11c)
(depend :level12 :level11d)
(depend :level13a :level12)
(depend :level13b :level12)
(depend :level13c :level12)
(depend :level13d :level12)
(depend :level14 :level13a)
(depend :level14 :level13b)
(depend :level14 :level13c)
(depend :level14 :level13d)
(depend :level15a :level14)
(depend :level15b :level14)
(depend :level15c :level14)
(depend :level15d :level14)
(depend :level16 :level15a)
(depend :level16 :level15b)
(depend :level16 :level15c)
(depend :level16 :level15d)
(depend :level17a :level16)
(depend :level17b :level16)
(depend :level17c :level16)
(depend :level17d :level16)
(depend :level18 :level17a)
(depend :level18 :level17b)
(depend :level18 :level17c)
(depend :level18 :level17d)
(depend :level19a :level18)
(depend :level19b :level18)
(depend :level19c :level18)
(depend :level19d :level18)
(depend :level20 :level19a)
(depend :level20 :level19b)
(depend :level20 :level19c)
(depend :level20 :level19d)
(depend :level21a :level20)
(depend :level21b :level20)
(depend :level21c :level20)
(depend :level21d :level20)
(depend :level22 :level21a)
(depend :level22 :level21b)
(depend :level22 :level21c)
(depend :level22 :level21d)
(depend :level23a :level22)
(depend :level23b :level22)
(depend :level23c :level22)
(depend :level23d :level22)
(depend :level24 :level23a)
(depend :level24 :level23b)
(depend :level24 :level23c)
(depend :level24 :level23d)
(depend :level25a :level24)
(depend :level25b :level24)
(depend :level25c :level24)
(depend :level25d :level24)
(depend :level26 :level25a)
(depend :level26 :level25b)
(depend :level26 :level25c)
(depend :level26 :level25d)))
(deftest t-transitive-dependencies
(is (= #{:a :c :b}
(transitive-dependencies g1 :d)))
(is (= '#{two four six one five three}
(transitive-dependencies g2 'seven))))
(deftest t-transitive-dependencies-deep
(is (= #{:level0
:level1a :level1b :level1c :level1d
:level2
:level3a :level3b :level3c :level3d
:level4
:level5a :level5b :level5c :level5d
:level6
:level7a :level7b :level7c :level7d
:level8
:level9a :level9b :level9c :level9d
:level10
:level11a :level11b :level11c :level11d
:level12
:level13a :level13b :level13c :level13d
:level14
:level15a :level15b :level15c :level15d
:level16
:level17a :level17b :level17c :level17d
:level18
:level19a :level19b :level19c :level19d
:level20
:level21a :level21b :level21c :level21d
:level22
:level23a :level23b :level23c :level23d}
(transitive-dependencies g3 :level24)))
(is (= #{:level0
:level1a :level1b :level1c :level1d
:level2
:level3a :level3b :level3c :level3d
:level4
:level5a :level5b :level5c :level5d
:level6
:level7a :level7b :level7c :level7d
:level8
:level9a :level9b :level9c :level9d
:level10
:level11a :level11b :level11c :level11d
:level12
:level13a :level13b :level13c :level13d
:level14
:level15a :level15b :level15c :level15d
:level16
:level17a :level17b :level17c :level17d
:level18
:level19a :level19b :level19c :level19d
:level20
:level21a :level21b :level21c :level21d
:level22
:level23a :level23b :level23c :level23d
:level24
:level25a :level25b :level25c :level25d}
(transitive-dependencies g3 :level26))))
(deftest t-transitive-dependents
(is (= '#{four seven}
(transitive-dependents g2 'five)))
(is (= '#{four seven six three}
(transitive-dependents g2 'two))))
(defn- before?
"True if x comes before y in an ordered collection."
[coll x y]
(loop [[item & more] (seq coll)]
(cond (nil? item) true ; end of the seq
(= x item) true ; x comes first
(= y item) false
:else (recur more))))
(deftest t-before
(is (true? (before? [:a :b :c :d] :a :b)))
(is (true? (before? [:a :b :c :d] :b :c)))
(is (false? (before? [:a :b :c :d] :d :c)))
(is (false? (before? [:a :b :c :d] :c :a))))
(deftest t-topo-comparator-1
(let [sorted (sort (topo-comparator g1) [:d :a :b :foo])]
(are [x y] (before? sorted x y)
:a :b
:a :d
:a :foo
:b :d
:b :foo
:d :foo)))
(deftest t-topo-comparator-2
(let [sorted (sort (topo-comparator g2) '[three seven nine eight five])]
(are [x y] (before? sorted x y)
'three 'seven
'three 'eight
'three 'nine
'five 'eight
'five 'nine
'seven 'eight
'seven 'nine)))
(deftest t-topo-sort
(let [sorted (topo-sort g2)]
(are [x y] (before? sorted x y)
'one 'two
'one 'three
'one 'four
'one 'six
'one 'seven
'two 'three
'two 'four
'two 'six
'two 'seven
'three 'six
'three 'seven
'four 'seven
'five 'four
'five 'seven
'six 'seven)))
(deftest t-no-cycles
(is (thrown? Exception
(-> (graph)
(depend :a :b)
(depend :b :c)
(depend :c :a)))))
(deftest t-no-self-cycles
(is (thrown? Exception
(-> (graph)
(depend :a :b)
(depend :a :a)))))

View file

@ -0,0 +1,20 @@
(ns clojure.tools.namespace.dir-test
(:require [clojure.test :refer [deftest is]]
[clojure.tools.namespace.test-helpers :as help]
[clojure.tools.namespace.dir :as dir])
(:import
(java.io File)))
;; Only run this test on Java 1.7+, where java.nio.file.Files is available.
(when (try (Class/forName "java.nio.file.Files")
(catch ClassNotFoundException _ false))
(deftest t-scan-by-canonical-path
(let [dir (help/create-temp-dir "t-scan-by-canonical-path")
main-clj (help/create-source dir 'example.main :clj '[example.one])
one-cljc (help/create-source dir 'example.one :clj)
other-dir (help/create-temp-dir "t-scan-by-canonical-path-other")
link (File. other-dir "link")]
(java.nio.file.Files/createSymbolicLink (.toPath link) (.toPath dir)
(make-array java.nio.file.attribute.FileAttribute 0))
(is (= (::dir/files (dir/scan-dirs {} [dir]))
(::dir/files (dir/scan-dirs {} [link])))))))

View file

@ -0,0 +1,29 @@
(ns clojure.tools.namespace.find-test
(:require [clojure.test :refer [deftest is]]
[clojure.tools.namespace.test-helpers :as help]
[clojure.tools.namespace.find :as find])
(:import (java.io File)))
(deftest t-find-clj-and-cljc-files
"main.clj depends on one.cljc which depends on two.clj.
two.cljs also exists but should not be returned"
(let [dir (help/create-temp-dir "t-find-clj-and-cljc-files")
main-clj (help/create-source dir 'example.main :clj '[example.one])
one-cljc (help/create-source dir 'example.one :cljc '[example.two])
two-clj (help/create-source dir 'example.two :clj)
two-cljs (help/create-source dir 'example.two :cljs)]
(is (help/same-files?
[main-clj one-cljc two-clj]
(find/find-sources-in-dir dir)))))
(deftest t-find-cljs-and-cljc-files
"main.cljs depends on one.cljc which depends on two.cljs.
two.clj also exists but should not be returned"
(let [dir (help/create-temp-dir "t-find-cljs-and-cljc-files")
main-cljs (help/create-source dir 'example.main :cljs '[example.one])
one-cljc (help/create-source dir 'example.one :cljc '[example.two])
two-clj (help/create-source dir 'example.two :clj)
two-cljs (help/create-source dir 'example.two :cljs)]
(is (help/same-files?
[main-cljs one-cljc two-cljs]
(find/find-sources-in-dir dir find/cljs)))))

View file

@ -0,0 +1,52 @@
(ns clojure.tools.namespace.move-test
(:require [clojure.java.io :as io]
[clojure.test :refer [deftest is]]
[clojure.tools.namespace.move :refer [move-ns]]
[clojure.tools.namespace.test-helpers :as help])
(:import (java.io File)))
(defn- create-file-one [dir]
(help/create-source dir 'example.one :clj
'[example.two example.three]
'[(defn foo []
(example.a.four/foo))]))
(defn- create-file-two [dir]
(help/create-source dir 'example.two :clj
'[example.three example.a.four]))
(defn- create-file-three [dir]
(help/create-source dir 'example.three :clj
'[example.five]))
(defn- create-file-four [dir]
(help/create-source dir 'example.a.four :clj))
(deftest t-move-ns
(let [temp-dir (help/create-temp-dir "tools-namespace-t-move-ns")
src-dir (io/file temp-dir "src")
example-dir (io/file temp-dir "src" "example")
file-one (create-file-one src-dir)
file-two (create-file-two src-dir)
file-three (create-file-three src-dir)
old-file-four (create-file-four src-dir)
new-file-four (io/file example-dir "b" "four.clj")]
(let [file-three-last-modified (.lastModified file-three)]
(Thread/sleep 1500) ;; ensure file timestamps are different
(move-ns 'example.a.four 'example.b.four src-dir [src-dir])
(is (.exists new-file-four)
"new file should exist")
(is (not (.exists old-file-four))
"old file should not exist")
(is (not (.exists (.getParentFile old-file-four)))
"old empty directory should not exist")
(is (= file-three-last-modified (.lastModified file-three))
"unaffected file should not have been modified")
(is (not-any? #(.contains (slurp %) "example.a.four")
[file-one file-two file-three new-file-four]))
(is (every? #(.contains (slurp %) "example.b.four")
[file-one file-two new-file-four])))))

View file

@ -0,0 +1,210 @@
(ns clojure.tools.namespace.parse-test
(:use [clojure.test :only (deftest is)]
[clojure.tools.namespace.parse :only (deps-from-ns-decl
read-ns-decl)]))
(def ns-decl-prefix-list
'(ns com.example.one
(:require (com.example two
[three :as three]
[four :refer (a b)])
(com.example.sub [five :as five]
six))
(:use (com.example seven
[eight :as eight]
(nine :only (c d))
[ten]))))
;; Some people like to write prefix lists as vectors, not lists. The
;; use/require functions accept this form.
(def ns-decl-prefix-list-as-vector
'(ns com.example.one
(:require [com.example
two
[three :as three]
[four :refer (a b)]]
[com.example.sub
[five :as five]
six])
(:use [com.example
seven
[eight :as eight]
(nine :only (c d))
[ten]])))
(def ns-decl-prefix-list-clauses-as-vectors
"Sometimes people even write the clauses inside ns as vectors, which
clojure.core/ns allows. See TNS-21."
'(ns com.example.one
[:require [com.example
two
[three :as three]
[four :refer (a b)]]
[com.example.sub
[five :as five]
six]]
[:use [com.example
seven
[eight :as eight]
(nine :only (c d))
[ten]]]))
(def deps-from-prefix-list
'#{com.example.two
com.example.three
com.example.four
com.example.sub.five
com.example.sub.six
com.example.seven
com.example.eight
com.example.nine
com.example.ten})
(deftest t-prefix-list
(is (= deps-from-prefix-list
(deps-from-ns-decl ns-decl-prefix-list))))
(deftest t-prefix-list-as-vector
(is (= deps-from-prefix-list
(deps-from-ns-decl ns-decl-prefix-list-as-vector))))
(deftest t-prefix-list-clauses-as-vectors
(is (= deps-from-prefix-list
(deps-from-ns-decl ns-decl-prefix-list-clauses-as-vectors))))
(deftest t-no-deps-returns-empty-set
(is (= #{} (deps-from-ns-decl '(ns com.example.one)))))
(def multiple-ns-decls
'((ns one)
(ns two (:require one))
(ns three (:require [one :as o] [two :as t]))))
(def multiple-ns-decls-string
" (println \"Code before first ns\")
(ns one)
(println \"Some code\")
(defn hello-world [] \"Hello, World!\")
(ns two (:require one))
(println \"Some more code\")
(ns three (:require [one :as o] [two :as t]))")
(deftest t-read-multiple-ns-decls
(with-open [rdr (clojure.lang.LineNumberingPushbackReader.
(java.io.PushbackReader.
(java.io.StringReader. multiple-ns-decls-string)))]
(is (= multiple-ns-decls
(take-while identity (repeatedly #(read-ns-decl rdr)))))))
(def ns-docstring-example
"The example ns declaration used in the docstring of clojure.core/ns"
'(ns foo.bar
(:refer-clojure :exclude [ancestors printf])
(:require (clojure.contrib sql combinatorics))
(:use (my.lib this that))
(:import (java.util Date Timer Random)
(java.sql Connection Statement))))
(def deps-from-ns-docstring-example
'#{clojure.contrib.sql
clojure.contrib.combinatorics
my.lib.this
my.lib.that})
(deftest t-ns-docstring-example
(is (= deps-from-ns-docstring-example
(deps-from-ns-decl ns-docstring-example))))
(def require-docstring-example
"The example ns declaration used in the docstring of
clojure.core/require"
'(ns (:require (clojure zip [set :as s]))))
(def deps-from-require-docstring-example
'#{clojure.zip
clojure.set})
(deftest t-require-docstring-example
(is (= deps-from-require-docstring-example
(deps-from-ns-decl require-docstring-example))))
(def multiple-clauses
"Example showing more than one :require or :use clause in one ns
declaration, which clojure.core/ns allows."
'(ns foo.bar
(:require com.example.one)
(:import java.io.File)
(:require (com.example two three))
(:use (com.example [four :only [x]]))
(:use (com.example (five :only [x])))))
(def deps-from-multiple-clauses
'#{com.example.one
com.example.two
com.example.three
com.example.four
com.example.five})
(deftest t-deps-from-multiple-clauses
(is (= deps-from-multiple-clauses
(deps-from-ns-decl multiple-clauses))))
(def clauses-without-keywords
"Example of require/use clauses with symbols instead of keywords,
which clojure.core/ns allows."
'(ns foo.bar
(require com.example.one)
(import java.io.File)
(use (com.example (prefixes (two :only [x])
three)))))
(def deps-from-clauses-without-keywords
'#{com.example.one
com.example.prefixes.two
com.example.prefixes.three})
(deftest t-clauses-without-keywords
(is (= deps-from-clauses-without-keywords
(deps-from-ns-decl clauses-without-keywords))))
(def reader-conditionals-string
"(ns com.examples.one
(:require #?(:clj clojure.string
:cljs goog.string)))")
(deftest t-reader-conditionals
;; TODO: the predicate wasn't added to bb yet, will come in version after 0.6.7
(when true #_(resolve 'clojure.core/reader-conditional?)
(let [actual (-> reader-conditionals-string
java.io.StringReader.
java.io.PushbackReader.
clojure.lang.LineNumberingPushbackReader.
read-ns-decl
deps-from-ns-decl)]
(is (= #{'clojure.string} actual)))))
(def ns-with-npm-dependency
"(ns com.examples.one
(:require [\"foobar\"] [baz]))")
(deftest npm-dependency
(let [actual (-> ns-with-npm-dependency
java.io.StringReader.
java.io.PushbackReader.
clojure.lang.LineNumberingPushbackReader.
read-ns-decl
deps-from-ns-decl)]
(is (= #{'baz} actual))))
(def ns-with-require-macros
"(ns com.examples.one
(:require-macros [foo :refer [bar]]))")
(deftest require-macros
(let [actual (-> ns-with-require-macros
java.io.StringReader.
java.io.PushbackReader.
clojure.lang.LineNumberingPushbackReader.
read-ns-decl
deps-from-ns-decl)]
(is (= #{'foo} actual))))

View file

@ -0,0 +1,82 @@
(ns clojure.tools.namespace.test-helpers
"Utilities to help with testing files and namespaces."
(:require [clojure.java.io :as io]
[clojure.string :as string])
(:import (java.io Closeable File Writer PrintWriter)))
(defn create-temp-dir
"Creates and returns a new temporary directory java.io.File."
[name]
(let [temp-file (File/createTempFile name nil)]
(.delete temp-file)
(.mkdirs temp-file)
(println "Temporary directory" (.getAbsolutePath temp-file))
temp-file))
(defn- write-contents
"Writes contents into writer. Strings are written as-is via println,
other types written as by prn."
[^Writer writer contents]
{:pre [(sequential? contents)]}
(binding [*out* (PrintWriter. writer)]
(doseq [content contents]
(if (string? content)
(println content)
(prn content))
(newline))))
(defn create-file
"Creates a file from a vector of path elements. Writes contents into
the file. Elements of contents may be data, written via prn, or
strings, written directly."
[path contents]
{:pre [(vector? path)]}
(let [^File file (apply io/file path)]
(when-let [parent (.getParentFile file)]
(.mkdirs parent))
(with-open [wtr (io/writer file)]
(write-contents wtr contents))
file))
(defn- sym->path
"Converts a symbol name into a vector of path parts, not including
file extension."
[symbol]
{:pre [(symbol? symbol)]
:post [(vector? %)]}
(-> (name symbol)
(string/replace \- \_)
(string/split #"\.")))
(defn- source-path
"Returns a vector of path components for namespace named sym,
with given file extension (keyword)."
[sym extension]
(let [path (sym->path sym)
basename (peek path)
filename (str basename \. (name extension))]
(conj (pop path) filename)))
(defn create-source
"Creates a file at the correct path under base-dir for a namespace
named sym, with file extension (keyword), containing a ns
declaration which :require's the dependencies (symbols). Optional
contents written after the ns declaration as by write-contents."
([base-dir sym extension]
(create-source base-dir sym extension nil nil))
([base-dir sym extension dependencies]
(create-source base-dir sym extension dependencies nil))
([base-dir sym extension dependencies contents]
(let [full-path (into [base-dir] (source-path sym extension))
ns-decl (if (seq dependencies)
(list 'ns sym (list* :require dependencies))
(list 'ns sym))]
(create-file full-path (into [ns-decl] contents)))))
(defn same-files?
"True if files-a and files-b contain the same canonical File's,
regardless of order."
[files-a files-b]
(= (sort (map #(.getCanonicalPath ^File %) files-a))
(sort (map #(.getCanonicalPath ^File %) files-b))))

View file

@ -0,0 +1,10 @@
(ns cognitect.test-runner.sample-property-test
(:require [clojure.test.check :as tc]
[clojure.test.check.generators :as gen]
[clojure.test.check.properties :as prop]
[clojure.test.check.clojure-test :refer [defspec]]))
(defspec first-element-is-min-after-sorting 100
(prop/for-all [v (gen/not-empty (gen/vector gen/int))]
(= (apply min v)
(first (sort v)))))

View file

@ -0,0 +1,14 @@
(ns cognitect.test-runner.samples-test
(:require [clojure.test :as t :refer [deftest is testing]]))
(deftest math-works
(testing "basic addition and subtraction"
(is (= 42 (+ 40 2)))
(is (= 42 (- 44 2)))))
(deftest ^:integration test-i
(is (= 1 1)))

View file

@ -0,0 +1,23 @@
(ns cognitect.test-runner-test
(:require
[clojure.test :refer :all]
[cognitect.test-runner :as tr]))
(deftest ns-filters
(are [ns-names ns-regexes available selected]
(= selected (filter (#'tr/ns-filter {:namespace ns-names :namespace-regex ns-regexes}) available))
;; default settings (no -n / -r, use default for -r)
nil nil nil []
nil nil '[ns1-test ns2-test] '[ns1-test ns2-test]
nil nil '[ns1-test ns2-test ns3 ns4 ns5] '[ns1-test ns2-test]
;; specific namespaces
'#{ns3} nil '[ns1-test ns2-test] '[]
'#{ns3 ns4} nil '[ns1-test ns2-test ns3 ns4 ns5] '[ns3 ns4]
;; regexes
nil #{#"ns1.*" #"ns3"} '[ns1-test ns2-test ns3 ns4] '[ns1-test ns3]
;; both
'#{ns3} '#{#"ns1.*"} '[ns1-test ns2-test ns3 ns4] '[ns1-test ns3]))

View file

@ -0,0 +1,307 @@
(ns com.stuartsierra.component-test
(:require [clojure.test :refer (deftest is are)]
[clojure.set :refer (map-invert)]
[com.stuartsierra.component :as component]))
(def ^:dynamic *log* nil)
(defn- log [& args]
(when (thread-bound? #'*log*)
(set! *log* (conj *log* args))))
(defn- ordering
"Given an ordered collection of messages, returns a map from the
head of each message to its index position in the collection."
[log]
(into {} (map-indexed (fn [i [message & _]] [message i]) log)))
(defn before?
"In the collection of messages, does the message beginning with
symbol a come before the message begging with symbol b?"
[log sym-a sym-b]
(let [order (ordering log)]
(< (get order sym-a) (get order sym-b))))
(defn started? [component]
(true? (::started? component)))
(defn stopped? [component]
(false? (::started? component)))
(defrecord ComponentA [state]
component/Lifecycle
(start [this]
(log 'ComponentA.start this)
(assoc this ::started? true))
(stop [this]
(log 'ComponentA.stop this)
(assoc this ::started? false)))
(defn component-a []
(->ComponentA (rand-int Integer/MAX_VALUE)))
(defrecord ComponentB [state a]
component/Lifecycle
(start [this]
(log 'ComponentB.start this)
(assert (started? a))
(assoc this ::started? true))
(stop [this]
(log 'ComponentB.stop this)
(assert (started? a))
(assoc this ::started? false)))
(defn component-b []
(component/using
(map->ComponentB {:state (rand-int Integer/MAX_VALUE)})
[:a]))
(defrecord ComponentC [state a b]
component/Lifecycle
(start [this]
(log 'ComponentC.start this)
(assert (started? a))
(assert (started? b))
(assoc this ::started? true))
(stop [this]
(log 'ComponentC.stop this)
(assert (started? a))
(assert (started? b))
(assoc this ::started? false)))
(defn component-c []
(component/using
(map->ComponentC {:state (rand-int Integer/MAX_VALUE)})
[:a :b]))
(defrecord ComponentD [state my-c b]
component/Lifecycle
(start [this]
(log 'ComponentD.start this)
(assert (started? b))
(assert (started? my-c))
(assoc this ::started? true))
(stop [this]
(log 'ComponentD.stop this)
(assert (started? b))
(assert (started? my-c))
(assoc this ::started? false)))
(defn component-d []
(map->ComponentD {:state (rand-int Integer/MAX_VALUE)}))
(defrecord ComponentE [state]
component/Lifecycle
(start [this]
(log 'ComponentE.start this)
(assoc this ::started? true))
(stop [this]
(log 'ComponentE.stop this)
(assoc this ::started? false)))
(defn component-e []
(map->ComponentE {:state (rand-int Integer/MAX_VALUE)}))
(defrecord System1 [d a e c b] ; deliberately scrambled order
component/Lifecycle
(start [this]
(log 'System1.start this)
(component/start-system this))
(stop [this]
(log 'System1.stop this)
(component/stop-system this)))
(defn system-1 []
(map->System1 {:a (component-a)
:b (component-b)
:c (component-c)
:d (component/using (component-d)
{:b :b
:my-c :c})
:e (component-e)}))
(defmacro with-log [& body]
`(binding [*log* []]
~@body
*log*))
(deftest components-start-in-order
(let [log (with-log (component/start (system-1)))]
(are [k1 k2] (before? log k1 k2)
'ComponentA.start 'ComponentB.start
'ComponentA.start 'ComponentC.start
'ComponentB.start 'ComponentC.start
'ComponentC.start 'ComponentD.start
'ComponentB.start 'ComponentD.start)))
(deftest all-components-started
(let [system (component/start (system-1))]
(doseq [component (vals system)]
(is (started? component)))))
(deftest all-components-stopped
(let [system (component/stop (component/start (system-1)))]
(doseq [component (vals system)]
(is (stopped? component)))))
(deftest dependencies-satisfied
(let [system (component/start (component/start (system-1)))]
(are [keys] (started? (get-in system keys))
[:b :a]
[:c :a]
[:c :b]
[:d :my-c])))
(defrecord ErrorStartComponentC [state error a b]
component/Lifecycle
(start [this]
(throw error))
(stop [this]
this))
(defn error-start-c [error]
(component/using
(map->ErrorStartComponentC {:error error})
[:a :b]))
(defn setup-error
([]
(setup-error (ex-info "Boom!" {})))
([error]
(try (component/start
(assoc (system-1) :c (error-start-c error)))
(catch Exception e e))))
(deftest error-thrown-with-partial-system
(let [ex (setup-error)]
(is (started? (-> ex ex-data :system :b :a)))))
(deftest error-thrown-with-component-dependencies
(let [ex (setup-error)]
(is (started? (-> ex ex-data :component :a)))
(is (started? (-> ex ex-data :component :b)))))
(deftest error-thrown-with-cause
(let [error (ex-info "Boom!" {})
ex (setup-error error)]
(is (identical? error (.getCause ^Exception ex)))))
(deftest error-is-from-component
(let [error (ex-info "Boom!" {})
ex (setup-error error)]
(is (component/ex-component? ex))))
(deftest error-is-not-from-component
(is (not (component/ex-component? (ex-info "Boom!" {})))))
(deftest remove-components-from-error
(let [error (ex-info (str (rand-int Integer/MAX_VALUE)) {})
^Exception ex (setup-error error)
^Exception ex-without (component/ex-without-components ex)]
(is (contains? (ex-data ex) :component))
(is (contains? (ex-data ex) :system))
(is (not (contains? (ex-data ex-without) :component)))
(is (not (contains? (ex-data ex-without) :system)))
(is (= (.getMessage ex)
(.getMessage ex-without)))
(is (= (.getCause ex)
(.getCause ex-without)))
(is (java.util.Arrays/equals
(.getStackTrace ex)
(.getStackTrace ex-without)))))
(defrecord System2b [one]
component/Lifecycle
(start [this]
(assert (started? (get-in one [:b :a])))
this)
(stop [this]
(assert (started? (get-in one [:b :a])))
this))
(defn system-2 []
(component/system-map :alpha (system-1)
:beta (component/using (->System2b nil)
{:one :alpha})))
(deftest composed-systems
(let [system (component/start (system-2))]
(is (started? (get-in system [:beta :one :d :my-c])))))
(defn increment-all-components [system]
(component/update-system
system (keys system) update-in [:n] inc))
(defn assert-increments [system]
(are [n keys] (= n (get-in system keys))
11 [:a :n]
11 [:b :a :n]
11 [:c :a :n]
11 [:c :b :a :n]
11 [:e :d :b :a :n]
21 [:b :n]
21 [:c :b :n]
21 [:d :b :n]
31 [:c :n]
41 [:d :n]
51 [:e :n]))
(deftest update-with-custom-function-on-maps
(let [system {:a {:n 10}
:b (component/using {:n 20} [:a])
:c (component/using {:n 30} [:a :b])
:d (component/using {:n 40} [:a :b])
:e (component/using {:n 50} [:b :c :d])}]
(assert-increments (increment-all-components system))))
(deftest t-system-using
(let [dependency-map {:b [:a]
:c [:a :b]
:d {:a :a :b :b}
:e [:b :c :d]}
system {:a {:n 10}
:b {:n 20}
:c {:n 30}
:d {:n 40}
:e {:n 50}}
system (component/system-using system dependency-map)]
(assert-increments (increment-all-components system))))
(defrecord ComponentWithoutLifecycle [state])
;; BB-TEST-PATCH: No implementation of method errors for start and stop
#_(deftest component-without-lifecycle
(let [c (->ComponentWithoutLifecycle nil)]
(is (= c (component/start c)))
(is (= c (component/stop c)))))
(defrecord ComponentReturningNil [state]
component/Lifecycle
(start [this]
nil)
(stop [this]
nil))
(deftest component-returning-nil
(let [a (->ComponentReturningNil nil)
s (component/system-map :a a :b (component-b))
e (try (component/start s)
false
(catch Exception e e))]
(is (= ::component/nil-component (:reason (ex-data e))))))
(deftest missing-dependency-error
(let [system-key ::system-b
local-key ::local-b
a (component/using (component-a) {local-key system-key})
system (component/system-map
:a a)
e (try (component/start system)
false
(catch Exception e e))
data (ex-data e)]
(is (= ::component/missing-dependency (:reason data)))
(is (= system-key (:system-key data)))
(is (= local-key (:dependency-key data)))
(is (= a (:component data)))
(is (= system (:system data)))))

View file

@ -0,0 +1,257 @@
(ns com.wsscode.misc.coll-test
(:require
[clojure.test :refer [deftest is are run-tests testing]]
[com.wsscode.misc.coll :as coll]))
(deftest distinct-by-test
(is (= (coll/distinct-by :id
[{:id 1
:name "foo"}
{:id 2
:name "bar"}
{:id 1
:name "other"}])
[{:id 1
:name "foo"}
{:id 2
:name "bar"}])))
(deftest dedupe-by-test
(is (= (coll/dedupe-by :id
[{:id 1
:name "foo"}
{:id 1
:name "dedup-me"}
{:id 2
:name "bar"}
{:id 1
:name "other"}])
[{:id 1
:name "foo"}
{:id 2
:name "bar"}
{:id 1
:name "other"}])))
(deftest index-by-test
(is (= (coll/index-by :id
[{:id 1
:name "foo"}
{:id 1
:name "dedup-me"}
{:id 2
:name "bar"}
{:id 1
:name "other"}])
{1 {:id 1, :name "other"}, 2 {:id 2, :name "bar"}})))
(deftest find-first-test
(is (= (coll/find-first even? [1 2 3 4])
2)))
(deftest sconj-test
(is (= (coll/sconj nil 42) #{42}))
(is (set? (coll/sconj nil 42))))
(deftest vconj-test
(is (= (coll/vconj nil 42) [42]))
(is (vector? (coll/vconj nil 42))))
(deftest queue-test
(let [queue (-> (coll/queue)
(conj 1 2))]
(is (= queue [1 2]))
(is (= (peek queue) 1))
(is (= (pop queue) [2])))
(let [queue (coll/queue [1 2])]
(is (= queue [1 2]))
(is (= (peek queue) 1))
(is (= (pop queue) [2]))))
(deftest map-keys-test
(is (= (coll/map-keys inc {1 :a 2 :b})
{2 :a 3 :b})))
(deftest filter-keys-test
(is (= (coll/filter-keys simple-keyword? {1 :a 2 :b "foo" 3 :bar 4})
{:bar 4})))
(deftest filter-vals-test
(is (= (coll/filter-vals simple-keyword? {1 :a 2 :b "foo" 3 :bar 4})
{1 :a 2 :b})))
(deftest remove-keys-test
(is (= (coll/remove-keys number? {1 :a 2 :b "foo" 3 :bar 4})
{"foo" 3 :bar 4})))
(deftest remove-vals-test
(is (= (coll/remove-vals number? {1 :a 2 :b "foo" 3 :bar 4})
{1 :a 2 :b})))
(deftest map-vals-test
(is (= (coll/map-vals inc {:a 1 :b 2})
{:a 2 :b 3})))
(deftest keys-set-test
(is (= (coll/keys-set {:a 1 :b 2}) #{:a :b}))
(is (= (coll/keys-set 5) nil)))
(deftest merge-grow-test
(is (= (coll/merge-grow) {}))
(is (= (coll/merge-grow {:foo "bar"}) {:foo "bar"}))
(testing "merge sets by union"
(is (= (coll/merge-grow {:foo #{:a}} {:foo #{:b}})
{:foo #{:a :b}})))
(testing "merge maps"
(is (= (coll/merge-grow {:foo {:a 1}} {:foo {:b 2}})
{:foo {:a 1 :b 2}})))
(testing "keep left value if right one is nil"
(is (= (coll/merge-grow {:foo {:a 1}} {:foo {:a nil}})
{:foo {:a 1}}))))
(deftest merge-defaults-test
(is (= (coll/merge-defaults {:a 1} {:b 2})
{:a 1 :b 2}))
(is (= (coll/merge-defaults {:a 1} {:a 2})
{:a 1})))
(deftest assoc-if-test
(is (= (coll/assoc-if {} :foo "bar")
{:foo "bar"}))
(is (= (coll/assoc-if {} :foo nil)
{}))
(is (= (coll/assoc-if {} :foo false)
{}))
(is (= (coll/assoc-if {} :foo false :bar 30)
{:bar 30}))
(is (= (coll/assoc-if {} :foo false :bar 30 :baz false)
{:bar 30})))
(deftest update-contained-test
(is (= (coll/update-contained {:foo 3} :foo inc)
{:foo 4}))
(is (= (coll/update-contained {:foo nil} :foo #(str % " bla"))
{:foo " bla"}))
(is (= (coll/update-contained {} :foo inc)
{})))
(deftest update-if-test
(is (= (coll/update-if {:foo 3} :foo inc)
{:foo 4}))
(is (= (coll/update-if {:foo nil} :foo inc)
{:foo nil}))
(is (= (coll/update-if {} :foo inc)
{})))
(defrecord CustomRecord [])
(deftest native-map?-test
(is (= true (coll/native-map? {})))
(is (= true (coll/native-map? {:foo "bar"})))
(is (= true (coll/native-map? (zipmap (range 50) (range 50)))))
(is (= false (coll/native-map? (->CustomRecord)))))
(deftest restore-order-test
(is (= (coll/restore-order
[{:my.entity/id 1} {:my.entity/id 2}]
:my.entity/id
[{:my.entity/id 2
:my.entity/color :my.entity.color/green}
{:my.entity/id 1
:my.entity/color :my.entity.color/purple}])
[{:my.entity/id 1
:my.entity/color :my.entity.color/purple}
{:my.entity/id 2
:my.entity/color :my.entity.color/green}]))
(is (= (coll/restore-order
[{:my.entity/id 1}
{:my.entity/id 2}
{:my.entity/id 3}]
:my.entity/id
[{:my.entity/id 3
:my.entity/color :my.entity.color/green}
{:my.entity/id 1
:my.entity/color :my.entity.color/purple}])
[{:my.entity/id 1
:my.entity/color :my.entity.color/purple}
{:my.entity/id 2}
{:my.entity/id 3
:my.entity/color :my.entity.color/green}]))
(is (= (coll/restore-order [{:my.entity/id 1}
{:my.entity/id 2}
{:my.entity/id 3}]
:my.entity/id
[{:my.entity/id 3
:my.entity/color :my.entity.color/green}
{:my.entity/id 1
:my.entity/color :my.entity.color/purple}]
(fn [x] (assoc x :my.entity/color nil)))
[{:my.entity/id 1
:my.entity/color :my.entity.color/purple}
{:my.entity/id 2
:my.entity/color nil}
{:my.entity/id 3
:my.entity/color :my.entity.color/green}])))
(deftest conj-at-index-test
(is (= (coll/conj-at-index [:a :b] 0 :c)
[:c :a :b]))
(is (= (coll/conj-at-index [:a :b] 1 :c)
[:a :c :b]))
(is (= (coll/conj-at-index [:a :b] 2 :c)
[:a :b :c])))
(deftest index-of-test
(is (= (coll/index-of [:a {:id :b} :c] :not-here)
nil))
(is (= (coll/index-of [:a {:id :b} :c] :a)
0))
(is (= (coll/index-of [:a {:id :b} :c] {:id :b})
1)))
(deftest coll-append-ahead?-test
(is (true? (coll/coll-append-at-head? (list "foo"))))
(is (true? (coll/coll-append-at-head? (map identity ["foo"]))))
(is (false? (coll/coll-append-at-head? ["foo"])))
(is (false? (coll/coll-append-at-head? #{"foo"}))))
(deftest collection?-test
(is (true? (coll/collection? [])))
(is (true? (coll/collection? '())))
(is (true? (coll/collection? #{})))
(is (true? (coll/collection? (map identity []))))
(is (false? (coll/collection? {}))))
(deftest vector-compare-test
(is (= (coll/vector-compare [0] [1])
-1))
(is (= (coll/vector-compare [1] [0])
1))
(is (= (coll/vector-compare [1] [1])
0))
(is (= (coll/vector-compare [2 0] [2 1])
-1))
(is (= (coll/vector-compare [2 0 0] [2 1])
-1)))
(deftest iterate-while-test
(is (= (coll/iterate-while :n {:x 1 :n {:x 2 :n {:x 3}}})
[{:x 1, :n {:x 2, :n {:x 3}}} {:x 2, :n {:x 3}} {:x 3}])))
(deftest deep-merge-test
(is (= (coll/deep-merge {:a 1} {:b 2})
{:a 1 :b 2}))
(is (= (coll/deep-merge {:a {:x 1 :foo "bar"}} {:a {:baz "f" :foo "2"}})
{:a {:baz "f" :foo "2" :x 1}}))
(is (= (coll/deep-merge {:a [{:a 1}]} {:a [{:b 2}]})
{:a [{:b 2}]})))

View file

@ -0,0 +1,14 @@
(ns com.wsscode.misc.macros-test
(:require
[clojure.test :refer [deftest is are run-tests testing]]
[com.wsscode.misc.macros :as macros]))
(deftest full-symbol-test
(is (= (macros/full-symbol
'known/foo
"bar")
'known/foo))
(is (= (macros/full-symbol
'foo
"bar")
'bar/foo)))

View file

@ -0,0 +1,28 @@
(ns com.wsscode.misc.math-test
(:require
[clojure.test :refer [deftest is are run-tests testing]]
[com.wsscode.misc.math :as math]))
(deftest floor-test
(is (= (math/floor 30.2) 30))
(is (= (math/floor 30.9) 30)))
(deftest round-test
(is (= (math/round 30.2) 30))
(is (= (math/round 30.6) 31)))
(deftest ceil-test
(is (= (math/ceil 30.2) 31))
(is (= (math/ceil 30.9) 31)))
(deftest divmod-test
(is (= (math/divmod 10 3)
[3 1])))
(deftest parse-long-test
(is (= (math/parse-long "21")
21)))
(deftest parse-double-test
(is (= (math/parse-double "21.3")
21.3)))

View file

@ -0,0 +1,36 @@
(ns com.wsscode.misc.refs-test
(:require
[clojure.test :refer [deftest is are run-tests testing]]
[com.wsscode.misc.refs :refer [atom?] :as refs]))
(deftest kw-identical?-test
(is (not (refs/kw-identical? :foo :bar)))
(is (not (refs/kw-identical? :foo "foo")))
(is (refs/kw-identical? :foo :foo))
(is (refs/kw-identical? :foo (keyword "foo"))))
(deftest atom?-test
(is (true? (atom? (atom "x"))))
(is (false? (atom? "x"))))
(deftest greset!-test
(let [x (atom nil)]
(refs/greset! x "val")
(is (= @x "val")))
(let [x (volatile! nil)]
(refs/greset! x "val")
(is (= @x "val"))))
(deftest gswap!-test
(let [x (atom 10)]
(refs/gswap! x inc)
(is (= @x 11)))
(let [x (volatile! 10)]
(refs/gswap! x inc)
(is (= @x 11)))
(let [x (volatile! 10)]
(refs/gswap! x + 1 2 3 4 5)
(is (= @x 25))))

View file

@ -0,0 +1,7 @@
(ns com.wsscode.misc.uuid-test
(:require
[clojure.test :refer [deftest is are run-tests testing]]
[com.wsscode.misc.uuid :as uuid]))
(deftest cljc-random-uuid-test
(is (uuid? (uuid/cljc-random-uuid))))

View file

@ -1,41 +0,0 @@
(ns component.component-test
(:require [clojure.test :refer [deftest is testing]]
[com.stuartsierra.component :as component]))
(def syslog (atom []))
(defn log [msg]
(swap! syslog conj msg))
(defrecord FakeDB [state]
component/Lifecycle
(start [_]
(log "start DB"))
(stop [_]
(log "stop DB")))
(defrecord FakeApp [db]
component/Lifecycle
(start [_]
(log "start app"))
(stop [_]
(log "stop app")))
(defn base-app []
(map->FakeApp {}))
(def sm
(component/system-map
:db (->FakeDB :foo)
:app (component/using (base-app) [:db])))
(component/start sm)
;; do useful stuff here
(component/stop sm)
(deftest ordering-test
(testing "components are started and stopped in expected order"
(is (= ["start DB" "start app" "stop app" "stop DB"] @syslog))))

View file

@ -0,0 +1,22 @@
(ns contajners.core-test
(:require [clojure.test :as t]
[contajners.core :as c]))
(t/deftest docker-tests
(let [image "busybox:musl"
client (c/client {:engine :docker
:version "v1.41"
:category :images
:conn {:uri "unix:///var/run/docker.sock"}})]
(t/testing "pull an image"
(c/invoke client
{:op :ImageCreate
:params {:fromImage image}})
(let [images (c/invoke client {:op :ImageList})]
(t/is (contains? (->> images
(mapcat :RepoTags)
(into #{}))
image)))
(c/invoke client
{:op :ImageDelete
:params {:name image}}))))

View file

@ -0,0 +1,45 @@
(ns contajners.impl-test
(:require
[clojure.test :as t]
[contajners.impl :as impl]))
(t/deftest meta-cleanup
(t/testing "remove internal namespace"
(t/is (= [:foo]
(impl/remove-internal-meta [:contajners/foo :foo])))))
(t/deftest param-gathering
(t/testing "gathering params as header query and path"
(t/is (= {:header {:a 1 :b 2}
:query {:c 3 :d 4}
:path {:e 5 :f 6}}
(reduce (partial impl/gather-params {:a 1 :b 2 :c 3 :d 4 :e 5 :f 6})
{}
[{:name "a" :in :header}
{:name "b" :in :header}
{:name "c" :in :query}
{:name "d" :in :query}
{:name "e" :in :path}
{:name "f" :in :path}])))))
(t/deftest body-serialization
(t/testing "body serialization when a map"
(t/is (= {:headers {"content-type" "application/json"}
:body "{\"a\":42}"}
(impl/maybe-serialize-body {:body {:a 42}}))))
(t/testing "body serialization when not a map"
(t/is (= {:body "yes"}
(impl/maybe-serialize-body {:body "yes"})))))
(t/deftest path-interpolation
(t/testing "path interpolation"
(t/is (= "/a/{w}/b/41/42"
(impl/interpolate-path "/a/{w}/b/{x}/{y}" {:x 41 :y 42 :z 43})))))
(t/deftest json-parsing
(t/testing "successful json parsing"
(t/is (= {:a 42}
(impl/try-json-parse "{\"a\":42}"))))
(t/testing "failed json parsing"
(t/is (= "yes"
(impl/try-json-parse "yes")))))

View file

@ -0,0 +1,7 @@
(ns cprop.smoke-test
(:require [clojure.test :as t :refer [deftest is]]
[cprop.core]
[cprop.source :refer [from-env]]))
(deftest from-env-test
(println (:cprop-env (from-env))))

View file

@ -0,0 +1,492 @@
(ns datalog.parser.impl-test
(:require #?(:cljs [cljs.test :refer-macros [is are deftest testing]]
:clj [clojure.test :refer [is are deftest testing]])
[datalog.parser.impl :as dp]
[datalog.parser.type :as t]
[datalog.parser.test.util])
(:import [clojure.lang ExceptionInfo]))
(deftest bindings
(are [form res] (= (dp/parse-binding form) res)
'?x
(t/->BindScalar (t/->Variable '?x))
'_
(t/->BindIgnore)
'[?x ...]
(t/->BindColl (t/->BindScalar (t/->Variable '?x)))
'[?x]
(t/->BindTuple [(t/->BindScalar (t/->Variable '?x))])
'[?x ?y]
(t/->BindTuple [(t/->BindScalar (t/->Variable '?x)) (t/->BindScalar (t/->Variable '?y))])
'[_ ?y]
(t/->BindTuple [(t/->BindIgnore) (t/->BindScalar (t/->Variable '?y))])
'[[_ [?x ...]] ...]
(t/->BindColl
(t/->BindTuple [(t/->BindIgnore)
(t/->BindColl
(t/->BindScalar (t/->Variable '?x)))]))
'[[?a ?b ?c]]
(t/->BindColl
(t/->BindTuple [(t/->BindScalar (t/->Variable '?a))
(t/->BindScalar (t/->Variable '?b))
(t/->BindScalar (t/->Variable '?c))])))
(is (thrown-with-msg? ExceptionInfo #"Cannot parse binding"
(dp/parse-binding :key))))
(deftest in
(are [form res] (= (dp/parse-in form) res)
'[?x]
[(t/->BindScalar (t/->Variable '?x))]
'[$ $1 % _ ?x]
[(t/->BindScalar (t/->SrcVar '$))
(t/->BindScalar (t/->SrcVar '$1))
(t/->BindScalar (t/->RulesVar))
(t/->BindIgnore)
(t/->BindScalar (t/->Variable '?x))]
'[$ [[_ [?x ...]] ...]]
[(t/->BindScalar (t/->SrcVar '$))
(t/->BindColl
(t/->BindTuple [(t/->BindIgnore)
(t/->BindColl
(t/->BindScalar (t/->Variable '?x)))]))])
(is (thrown-with-msg? ExceptionInfo #"Cannot parse binding"
(dp/parse-in ['?x :key]))))
(deftest with
(is (= (dp/parse-with '[?x ?y])
[(t/->Variable '?x) (t/->Variable '?y)]))
(is (thrown-with-msg? ExceptionInfo #"Cannot parse :with clause"
(dp/parse-with '[?x _]))))
(deftest test-parse-find
(is (= (dp/parse-find '[?a ?b])
(t/->FindRel [(t/->Variable '?a) (t/->Variable '?b)])))
(is (= (dp/parse-find '[[?a ...]])
(t/->FindColl (t/->Variable '?a))))
(is (= (dp/parse-find '[?a .])
(t/->FindScalar (t/->Variable '?a))))
(is (= (dp/parse-find '[[?a ?b]])
(t/->FindTuple [(t/->Variable '?a) (t/->Variable '?b)]))))
(deftest test-parse-aggregate
(is (= (dp/parse-find '[?a (count ?b)])
(t/->FindRel [(t/->Variable '?a) (t/->Aggregate (t/->PlainSymbol 'count) [(t/->Variable '?b)])])))
(is (= (dp/parse-find '[[(count ?a) ...]])
(t/->FindColl (t/->Aggregate (t/->PlainSymbol 'count) [(t/->Variable '?a)]))))
(is (= (dp/parse-find '[(count ?a) .])
(t/->FindScalar (t/->Aggregate (t/->PlainSymbol 'count) [(t/->Variable '?a)]))))
(is (= (dp/parse-find '[[(count ?a) ?b]])
(t/->FindTuple [(t/->Aggregate (t/->PlainSymbol 'count) [(t/->Variable '?a)]) (t/->Variable '?b)]))))
(deftest test-parse-custom-aggregates
(is (= (dp/parse-find '[(aggregate ?f ?a)])
(t/->FindRel [(t/->Aggregate (t/->Variable '?f) [(t/->Variable '?a)])])))
(is (= (dp/parse-find '[?a (aggregate ?f ?b)])
(t/->FindRel [(t/->Variable '?a) (t/->Aggregate (t/->Variable '?f) [(t/->Variable '?b)])])))
(is (= (dp/parse-find '[[(aggregate ?f ?a) ...]])
(t/->FindColl (t/->Aggregate (t/->Variable '?f) [(t/->Variable '?a)]))))
(is (= (dp/parse-find '[(aggregate ?f ?a) .])
(t/->FindScalar (t/->Aggregate (t/->Variable '?f) [(t/->Variable '?a)]))))
(is (= (dp/parse-find '[[(aggregate ?f ?a) ?b]])
(t/->FindTuple [(t/->Aggregate (t/->Variable '?f) [(t/->Variable '?a)]) (t/->Variable '?b)]))))
(deftest test-parse-find-elements
(is (= (dp/parse-find '[(count ?b 1 $x) .])
(t/->FindScalar (t/->Aggregate (t/->PlainSymbol 'count)
[(t/->Variable '?b)
(t/->Constant 1)
(t/->SrcVar '$x)])))))
(deftest clauses
(are [form res] (= (set (dp/parse-rules form)) res)
'[[(rule ?x)
[?x :name _]]]
#{(t/->Rule
(t/->PlainSymbol 'rule)
[(t/->RuleBranch
(t/->RuleVars nil [(t/->Variable '?x)])
[(t/->Pattern
(t/->DefaultSrc)
[(t/->Variable '?x) (t/->Constant :name) (t/->Placeholder)])])])})
(is (thrown-with-msg? ExceptionInfo #"Reference to the unknown variable"
(dp/parse-rules '[[(rule ?x) [?x :name ?y]]]))))
(deftest rule-vars
(are [form res] (= (set (dp/parse-rules form)) res)
'[[(rule [?x] ?y)
[_]]]
#{(t/->Rule
(t/->PlainSymbol 'rule)
[(t/->RuleBranch
(t/->RuleVars [(t/->Variable '?x)] [(t/->Variable '?y)])
[(t/->Pattern (t/->DefaultSrc) [(t/->Placeholder)])])])}
'[[(rule [?x ?y] ?a ?b)
[_]]]
#{(t/->Rule
(t/->PlainSymbol 'rule)
[(t/->RuleBranch
(t/->RuleVars [(t/->Variable '?x) (t/->Variable '?y)]
[(t/->Variable '?a) (t/->Variable '?b)])
[(t/->Pattern (t/->DefaultSrc) [(t/->Placeholder)])])])}
'[[(rule [?x])
[_]]]
#{(t/->Rule
(t/->PlainSymbol 'rule)
[(t/->RuleBranch
(t/->RuleVars [(t/->Variable '?x)] nil)
[(t/->Pattern (t/->DefaultSrc) [(t/->Placeholder)])])])})
(is (thrown-with-msg? ExceptionInfo #"Cannot parse rule-vars"
(dp/parse-rules '[[(rule) [_]]])))
(is (thrown-with-msg? ExceptionInfo #"Cannot parse rule-vars"
(dp/parse-rules '[[(rule []) [_]]])))
(is (thrown-with-msg? ExceptionInfo #"Rule variables should be distinct"
(dp/parse-rules '[[(rule ?x ?y ?x) [_]]])))
(is (thrown-with-msg? ExceptionInfo #"Rule variables should be distinct"
(dp/parse-rules '[[(rule [?x ?y] ?z ?x) [_]]]))))
(deftest branches
(are [form res] (= (set (dp/parse-rules form)) res)
'[[(rule ?x)
[:a]
[:b]]
[(rule ?x)
[:c]]]
#{(t/->Rule
(t/->PlainSymbol 'rule)
[(t/->RuleBranch
(t/->RuleVars nil [(t/->Variable '?x)])
[(t/->Pattern (t/->DefaultSrc) [(t/->Constant :a)])
(t/->Pattern (t/->DefaultSrc) [(t/->Constant :b)])])
(t/->RuleBranch
(t/->RuleVars nil [(t/->Variable '?x)])
[(t/->Pattern (t/->DefaultSrc) [(t/->Constant :c)])])])}
'[[(rule ?x)
[:a]
[:b]]
[(other ?x)
[:c]]]
#{(t/->Rule
(t/->PlainSymbol 'rule)
[(t/->RuleBranch
(t/->RuleVars nil [(t/->Variable '?x)])
[(t/->Pattern (t/->DefaultSrc) [(t/->Constant :a)])
(t/->Pattern (t/->DefaultSrc) [(t/->Constant :b)])])])
(t/->Rule
(t/->PlainSymbol 'other)
[(t/->RuleBranch
(t/->RuleVars nil [(t/->Variable '?x)])
[(t/->Pattern (t/->DefaultSrc) [(t/->Constant :c)])])])})
(is (thrown-with-msg? ExceptionInfo #"Rule branch should have clauses"
(dp/parse-rules '[[(rule ?x)]])))
(is (thrown-with-msg? ExceptionInfo #"Arity mismatch"
(dp/parse-rules '[[(rule ?x) [_]]
[(rule ?x ?y) [_]]])))
(is (thrown-with-msg? ExceptionInfo #"Arity mismatch"
(dp/parse-rules '[[(rule ?x) [_]]
[(rule [?x]) [_]]]))))
(deftest pattern
(are [clause pattern] (= (dp/parse-clause clause) pattern)
'[?e ?a ?v]
(t/->Pattern (t/->DefaultSrc) [(t/->Variable '?e) (t/->Variable '?a) (t/->Variable '?v)])
'[_ ?a _ _]
(t/->Pattern (t/->DefaultSrc) [(t/->Placeholder) (t/->Variable '?a) (t/->Placeholder) (t/->Placeholder)])
'[$x _ ?a _ _]
(t/->Pattern (t/->SrcVar '$x) [(t/->Placeholder) (t/->Variable '?a) (t/->Placeholder) (t/->Placeholder)])
'[$x _ :name ?v]
(t/->Pattern (t/->SrcVar '$x) [(t/->Placeholder) (t/->Constant :name) (t/->Variable '?v)])
'[$x _ sym ?v]
(t/->Pattern (t/->SrcVar '$x) [(t/->Placeholder) (t/->Constant 'sym) (t/->Variable '?v)])
'[$x _ $src-sym ?v]
(t/->Pattern (t/->SrcVar '$x) [(t/->Placeholder) (t/->Constant '$src-sym) (t/->Variable '?v)]))
(is (thrown-with-msg? ExceptionInfo #"Pattern could not be empty"
(dp/parse-clause '[]))))
(deftest test-pred
(are [clause res] (= (dp/parse-clause clause) res)
'[(pred ?a 1)]
(t/->Predicate (t/->PlainSymbol 'pred) [(t/->Variable '?a) (t/->Constant 1)])
'[(pred)]
(t/->Predicate (t/->PlainSymbol 'pred) [])
'[(?custom-pred ?a)]
(t/->Predicate (t/->Variable '?custom-pred) [(t/->Variable '?a)])))
(deftest test-fn
(are [clause res] (= (dp/parse-clause clause) res)
'[(fn ?a 1) ?x]
(t/->Function (t/->PlainSymbol 'fn) [(t/->Variable '?a) (t/->Constant 1)] (t/->BindScalar (t/->Variable '?x)))
'[(fn) ?x]
(t/->Function (t/->PlainSymbol 'fn) [] (t/->BindScalar (t/->Variable '?x)))
'[(?custom-fn) ?x]
(t/->Function (t/->Variable '?custom-fn) [] (t/->BindScalar (t/->Variable '?x)))
'[(?custom-fn ?arg) ?x]
(t/->Function (t/->Variable '?custom-fn) [(t/->Variable '?arg)] (t/->BindScalar (t/->Variable '?x)))))
(deftest rule-expr
(are [clause res] (= (dp/parse-clause clause) res)
'(friends ?x ?y)
(t/->RuleExpr (t/->DefaultSrc) (t/->PlainSymbol 'friends) [(t/->Variable '?x) (t/->Variable '?y)])
'(friends "Ivan" _)
(t/->RuleExpr (t/->DefaultSrc) (t/->PlainSymbol 'friends) [(t/->Constant "Ivan") (t/->Placeholder)])
'($1 friends ?x ?y)
(t/->RuleExpr (t/->SrcVar '$1) (t/->PlainSymbol 'friends) [(t/->Variable '?x) (t/->Variable '?y)])
'(friends something)
(t/->RuleExpr (t/->DefaultSrc) (t/->PlainSymbol 'friends) [(t/->Constant 'something)]))
(is (thrown-with-msg? ExceptionInfo #"rule-expr requires at least one argument"
(dp/parse-clause '(friends)))))
(deftest not-clause
(are [clause res] (= (dp/parse-clause clause) res)
'(not [?e :follows ?x])
(t/->Not
(t/->DefaultSrc)
[(t/->Variable '?e) (t/->Variable '?x)]
[(t/->Pattern
(t/->DefaultSrc)
[(t/->Variable '?e) (t/->Constant :follows) (t/->Variable '?x)])])
'(not
[?e :follows ?x]
[?x _ ?y])
(t/->Not
(t/->DefaultSrc)
[(t/->Variable '?e) (t/->Variable '?x) (t/->Variable '?y)]
[(t/->Pattern
(t/->DefaultSrc)
[(t/->Variable '?e) (t/->Constant :follows) (t/->Variable '?x)])
(t/->Pattern
(t/->DefaultSrc)
[(t/->Variable '?x) (t/->Placeholder) (t/->Variable '?y)])])
'($1 not [?x])
(t/->Not
(t/->SrcVar '$1)
[(t/->Variable '?x)]
[(t/->Pattern (t/->DefaultSrc) [(t/->Variable '?x)])])
'(not-join [?e ?y]
[?e :follows ?x]
[?x _ ?y])
(t/->Not
(t/->DefaultSrc)
[(t/->Variable '?e) (t/->Variable '?y)]
[(t/->Pattern
(t/->DefaultSrc)
[(t/->Variable '?e) (t/->Constant :follows) (t/->Variable '?x)])
(t/->Pattern
(t/->DefaultSrc)
[(t/->Variable '?x) (t/->Placeholder) (t/->Variable '?y)])])
'($1 not-join [?e] [?e :follows ?x])
(t/->Not
(t/->SrcVar '$1)
[(t/->Variable '?e)]
[(t/->Pattern
(t/->DefaultSrc)
[(t/->Variable '?e) (t/->Constant :follows) (t/->Variable '?x)])]))
(is (thrown-with-msg? ExceptionInfo #"Join variable not declared inside clauses: \[\?x\]"
(dp/parse-clause '(not-join [?x] [?y]))))
(is (thrown-with-msg? ExceptionInfo #"Join variables should not be empty"
(dp/parse-clause '(not-join [] [?y]))))
(is (thrown-with-msg? ExceptionInfo #"Join variables should not be empty"
(dp/parse-clause '(not [_]))))
(is (thrown-with-msg? ExceptionInfo #"Cannot parse 'not-join' clause"
(dp/parse-clause '(not-join [?x]))))
(is (thrown-with-msg? ExceptionInfo #"Cannot parse 'not' clause"
(dp/parse-clause '(not))))
(is (thrown-with-msg? ExceptionInfo #"Join variable not declared inside clauses: \[\?y\]"
(dp/parse-clause '(not-join [?y]
(not-join [?x]
[?x :follows ?y]))))))
(deftest or-clause
(are [clause res] (= (dp/parse-clause clause) res)
'(or [?e :follows ?x])
(t/->Or
(t/->DefaultSrc)
(t/->RuleVars nil [(t/->Variable '?e) (t/->Variable '?x)])
[(t/->Pattern
(t/->DefaultSrc)
[(t/->Variable '?e) (t/->Constant :follows) (t/->Variable '?x)])])
'(or
[?e :follows ?x]
[?e :friend ?x])
(t/->Or
(t/->DefaultSrc)
(t/->RuleVars nil [(t/->Variable '?e) (t/->Variable '?x)])
[(t/->Pattern
(t/->DefaultSrc)
[(t/->Variable '?e) (t/->Constant :follows) (t/->Variable '?x)])
(t/->Pattern
(t/->DefaultSrc)
[(t/->Variable '?e) (t/->Constant :friend) (t/->Variable '?x)])])
'(or
[?e :follows ?x]
(and
[?e :friend ?x]
[?x :friend ?e]))
(t/->Or
(t/->DefaultSrc)
(t/->RuleVars nil [(t/->Variable '?e) (t/->Variable '?x)])
[(t/->Pattern
(t/->DefaultSrc)
[(t/->Variable '?e) (t/->Constant :follows) (t/->Variable '?x)])
(t/->And
[(t/->Pattern
(t/->DefaultSrc)
[(t/->Variable '?e) (t/->Constant :friend) (t/->Variable '?x)])
(t/->Pattern
(t/->DefaultSrc)
[(t/->Variable '?x) (t/->Constant :friend) (t/->Variable '?e)])])])
'($1 or [?x])
(t/->Or
(t/->SrcVar '$1)
(t/->RuleVars nil [(t/->Variable '?x)])
[(t/->Pattern (t/->DefaultSrc) [(t/->Variable '?x)])])
'(or-join [?e]
[?e :follows ?x]
[?e :friend ?y])
(t/->Or
(t/->DefaultSrc)
(t/->RuleVars nil [(t/->Variable '?e)])
[(t/->Pattern
(t/->DefaultSrc)
[(t/->Variable '?e) (t/->Constant :follows) (t/->Variable '?x)])
(t/->Pattern
(t/->DefaultSrc)
[(t/->Variable '?e) (t/->Constant :friend) (t/->Variable '?y)])])
'(or-join [[?e]]
(and [?e :follows ?x]
[?e :friend ?y]))
(t/->Or
(t/->DefaultSrc)
(t/->RuleVars [(t/->Variable '?e)] nil)
[(t/->And
[(t/->Pattern
(t/->DefaultSrc)
[(t/->Variable '?e) (t/->Constant :follows) (t/->Variable '?x)])
(t/->Pattern
(t/->DefaultSrc)
[(t/->Variable '?e) (t/->Constant :friend) (t/->Variable '?y)])])])
'($1 or-join [[?e] ?x]
[?e :follows ?x])
(t/->Or
(t/->SrcVar '$1)
(t/->RuleVars [(t/->Variable '?e)] [(t/->Variable '?x)])
[(t/->Pattern
(t/->DefaultSrc)
[(t/->Variable '?e) (t/->Constant :follows) (t/->Variable '?x)])]))
;; These tests reflect the or-join semantics of Datomic Datalog, https://docs.datomic.com/on-prem/query.html
;; TODO use record constructors instead of wordy literals as for rest in this buffer
(is (= (dp/parse-clause '(or-join [?x] [?y]))
'#datalog.parser.type.Or{:source #datalog.parser.type.DefaultSrc{},
:rule-vars #datalog.parser.type.RuleVars{:required nil,
:free [#datalog.parser.type.Variable{:symbol ?x}]},
:clauses [#datalog.parser.type.Pattern{:source #datalog.parser.type.DefaultSrc{},
:pattern [#datalog.parser.type.Variable{:symbol ?y}]}]}))
(is (= (dp/parse-clause '(or-join [?x ?y] [?x ?y] [?y]))
'#datalog.parser.type.Or{:source #datalog.parser.type.DefaultSrc{},
:rule-vars #datalog.parser.type.RuleVars{:required nil,
:free [#datalog.parser.type.Variable{:symbol ?x}
#datalog.parser.type.Variable{:symbol ?y}]},
:clauses [#datalog.parser.type.Pattern{:source #datalog.parser.type.DefaultSrc{},
:pattern [#datalog.parser.type.Variable{:symbol ?x}
#datalog.parser.type.Variable{:symbol ?y}]}
#datalog.parser.type.Pattern{:source #datalog.parser.type.DefaultSrc{},
:pattern [#datalog.parser.type.Variable{:symbol ?y}]}]}))
(is (= (dp/parse-clause '(or-join [?y]
(or-join [?x]
[?x :follows ?y])))
'#datalog.parser.type.Or{:source #datalog.parser.type.DefaultSrc{},
:rule-vars #datalog.parser.type.RuleVars{:required nil,
:free [#datalog.parser.type.Variable{:symbol ?y}]},
:clauses [#datalog.parser.type.Or{:source #datalog.parser.type.DefaultSrc{},
:rule-vars #datalog.parser.type.RuleVars{:required nil,
:free [#datalog.parser.type.Variable{:symbol ?x}]},
:clauses [#datalog.parser.type.Pattern{:source #datalog.parser.type.DefaultSrc{},
:pattern [#datalog.parser.type.Variable{:symbol ?x}
#datalog.parser.type.Constant{:value :follows} #datalog.parser.type.Variable{:symbol ?y}]}]}]}))
(is (thrown-with-msg? ExceptionInfo #"Join variable not declared inside clauses: \[\?y\]"
(dp/parse-clause '(or [?x] [?x ?y]))))
(is (thrown-with-msg? ExceptionInfo #"Join variable not declared inside clauses: \[\?y\]"
(dp/parse-clause '(or [?x] [?y]))))
(is (thrown-with-msg? ExceptionInfo #"Cannot parse rule-vars"
(dp/parse-clause '(or-join [] [?y]))))
(is (thrown-with-msg? ExceptionInfo #"Join variables should not be empty"
(dp/parse-clause '(or [_]))))
(is (thrown-with-msg? ExceptionInfo #"Cannot parse 'or-join' clause"
(dp/parse-clause '(or-join [?x]))))
(is (thrown-with-msg? ExceptionInfo #"Cannot parse 'or' clause"
(dp/parse-clause '(or)))))
(deftest test-parse-return-maps
(testing "failed parsing"
(is (thrown-with-msg? ExceptionInfo #"Only one of these three options is allowed: :keys :strs :syms"
(dp/parse-return-maps {:keys '("keys" "strs" "syms") :syms '("keys" "strs" "syms")}))))
(testing "parsing correct options"
(is (= #datalog.parser.type.ReturnMaps{:mapping-type :keys, :mapping-keys (#datalog.parser.type.MappingKey{:mapping-key "keys"} #datalog.parser.type.MappingKey{:mapping-key "strs"} #datalog.parser.type.MappingKey{:mapping-key "syms"})}
(dp/parse-return-maps {:keys '("keys" "strs" "syms")})))
(is (= #datalog.parser.type.ReturnMaps{:mapping-type :strs, :mapping-keys (#datalog.parser.type.MappingKey{:mapping-key "keys"} #datalog.parser.type.MappingKey{:mapping-key "strs"} #datalog.parser.type.MappingKey{:mapping-key "syms"})}
(dp/parse-return-maps {:strs '("keys" "strs" "syms")})))
(is (= #datalog.parser.type.ReturnMaps{:mapping-type :syms, :mapping-keys (#datalog.parser.type.MappingKey{:mapping-key "keys"} #datalog.parser.type.MappingKey{:mapping-key "strs"} #datalog.parser.type.MappingKey{:mapping-key "syms"})}
(dp/parse-return-maps {:syms '("keys" "strs" "syms")})))))

View file

@ -0,0 +1,42 @@
(ns datalog.parser.pull-test
(:require [datalog.parser.pull :as dpp]
#?(:cljs [cljs.test :as t :refer-macros [is are deftest testing]]
:clj [clojure.test :as t :refer [is are deftest testing]])))
#?(:cljs
(def Throwable js/Error))
(deftest test-parse-pattern
(are [pattern expected] (= expected (dpp/parse-pull pattern))
'[:db/id :foo/bar]
(dpp/->PullSpec false {:db/id {:attr :db/id}
:foo/bar {:attr :foo/bar}})
'[(limit :foo 1)]
(dpp/->PullSpec false {:foo {:attr :foo :limit 1}})
'[* (default :foo "bar")]
(dpp/->PullSpec true {:foo {:attr :foo :default "bar"}})
'[{:foo ...}]
(dpp/->PullSpec false {:foo {:attr :foo :recursion nil}})
'[{(limit :foo 2) [:bar :me]}]
(dpp/->PullSpec
false
{:foo {:attr :foo
:limit 2
:subpattern (dpp/->PullSpec
false
{:bar {:attr :bar}
:me {:attr :me}})}})))
(deftest test-parse-bad-limit
(is
(thrown? Throwable (dpp/parse-pull '[(limit :foo :bar)]))))
(deftest test-parse-bad-default
(is
(thrown? Throwable (dpp/parse-pull '[(default 1 :bar)]))))
#_(t/test-ns 'datahike.test.pull-parser)

View file

@ -0,0 +1,16 @@
(ns datalog.parser.test.util
(:require [#?(:clj clojure.test :cljs cljs.test) :as test]))
#?(:clj
(defmethod test/assert-expr 'thrown-msg? [msg form]
(let [[_ match & body] form]
`(try ~@body
(test/do-report {:type :fail, :message ~msg, :expected '~form, :actual nil})
(catch Throwable e#
(let [m# (.getMessage e#)]
(test/do-report
{:type (if (= ~match m#) :pass :fail)
:message ~msg
:expected '~form
:actual e#}))
e#)))))

View file

@ -0,0 +1,96 @@
(ns datalog.parser-test
(:require #?(:cljs [cljs.test :refer-macros [are deftest]]
:clj [clojure.test :refer [are deftest]])
[datalog.parser :as parser]
[datalog.parser.test.util]))
(deftest validation
(are [q result] (= result (parser/parse q))
'[:find ?e
:in $ ?fname ?lname
:keys foo
:where [?e :user/firstName ?fname]
[?e :user/lastName ?lname]]
'#datalog.parser.type.Query{:qfind #datalog.parser.type.FindRel{:elements [#datalog.parser.type.Variable{:symbol ?e}]}, :qwith nil, :qin [#datalog.parser.type.BindScalar{:variable #datalog.parser.type.SrcVar{:symbol $}} #datalog.parser.type.BindScalar{:variable #datalog.parser.type.Variable{:symbol ?fname}} #datalog.parser.type.BindScalar{:variable #datalog.parser.type.Variable{:symbol ?lname}}], :qwhere [#datalog.parser.type.Pattern{:source #datalog.parser.type.DefaultSrc{}, :pattern [#datalog.parser.type.Variable{:symbol ?e} #datalog.parser.type.Constant{:value :user/firstName} #datalog.parser.type.Variable{:symbol ?fname}]} #datalog.parser.type.Pattern{:source #datalog.parser.type.DefaultSrc{}, :pattern [#datalog.parser.type.Variable{:symbol ?e} #datalog.parser.type.Constant{:value :user/lastName} #datalog.parser.type.Variable{:symbol ?lname}]}], :qlimit nil, :qoffset nil, :qreturnmaps #datalog.parser.type.ReturnMaps{:mapping-type :keys, :mapping-keys (#datalog.parser.type.MappingKey{:mapping-key foo})}}
'[:find ?e
:in $ ?fname ?lname
:strs foo
:where [?e :user/firstName ?fname]
[?e :user/lastName ?lname]]
'#datalog.parser.type.Query{:qfind #datalog.parser.type.FindRel{:elements [#datalog.parser.type.Variable{:symbol ?e}]}, :qwith nil, :qin [#datalog.parser.type.BindScalar{:variable #datalog.parser.type.SrcVar{:symbol $}} #datalog.parser.type.BindScalar{:variable #datalog.parser.type.Variable{:symbol ?fname}} #datalog.parser.type.BindScalar{:variable #datalog.parser.type.Variable{:symbol ?lname}}], :qwhere [#datalog.parser.type.Pattern{:source #datalog.parser.type.DefaultSrc{}, :pattern [#datalog.parser.type.Variable{:symbol ?e} #datalog.parser.type.Constant{:value :user/firstName} #datalog.parser.type.Variable{:symbol ?fname}]} #datalog.parser.type.Pattern{:source #datalog.parser.type.DefaultSrc{}, :pattern [#datalog.parser.type.Variable{:symbol ?e} #datalog.parser.type.Constant{:value :user/lastName} #datalog.parser.type.Variable{:symbol ?lname}]}], :qlimit nil, :qoffset nil, :qreturnmaps #datalog.parser.type.ReturnMaps{:mapping-type :strs, :mapping-keys (#datalog.parser.type.MappingKey{:mapping-key foo})}}
'[:find ?e
:in $ ?fname ?lname
:syms foo
:where [?e :user/firstName ?fname]
[?e :user/lastName ?lname]]
'#datalog.parser.type.Query{:qfind #datalog.parser.type.FindRel{:elements [#datalog.parser.type.Variable{:symbol ?e}]}, :qwith nil, :qin [#datalog.parser.type.BindScalar{:variable #datalog.parser.type.SrcVar{:symbol $}} #datalog.parser.type.BindScalar{:variable #datalog.parser.type.Variable{:symbol ?fname}} #datalog.parser.type.BindScalar{:variable #datalog.parser.type.Variable{:symbol ?lname}}], :qwhere [#datalog.parser.type.Pattern{:source #datalog.parser.type.DefaultSrc{}, :pattern [#datalog.parser.type.Variable{:symbol ?e} #datalog.parser.type.Constant{:value :user/firstName} #datalog.parser.type.Variable{:symbol ?fname}]} #datalog.parser.type.Pattern{:source #datalog.parser.type.DefaultSrc{}, :pattern [#datalog.parser.type.Variable{:symbol ?e} #datalog.parser.type.Constant{:value :user/lastName} #datalog.parser.type.Variable{:symbol ?lname}]}], :qlimit nil, :qoffset nil, :qreturnmaps #datalog.parser.type.ReturnMaps{:mapping-type :syms, :mapping-keys (#datalog.parser.type.MappingKey{:mapping-key foo})}}
'{:find [?e]
:in [$ ?fname ?lname]
:keys [foo]
:where [[?e :user/firstName ?fname]
[?e :user/lastName ?lname]]}
'#datalog.parser.type.Query{:qfind #datalog.parser.type.FindRel{:elements [#datalog.parser.type.Variable{:symbol ?e}]}, :qwith nil, :qin [#datalog.parser.type.BindScalar{:variable #datalog.parser.type.SrcVar{:symbol $}} #datalog.parser.type.BindScalar{:variable #datalog.parser.type.Variable{:symbol ?fname}} #datalog.parser.type.BindScalar{:variable #datalog.parser.type.Variable{:symbol ?lname}}], :qwhere [#datalog.parser.type.Pattern{:source #datalog.parser.type.DefaultSrc{}, :pattern [#datalog.parser.type.Variable{:symbol ?e} #datalog.parser.type.Constant{:value :user/firstName} #datalog.parser.type.Variable{:symbol ?fname}]} #datalog.parser.type.Pattern{:source #datalog.parser.type.DefaultSrc{}, :pattern [#datalog.parser.type.Variable{:symbol ?e} #datalog.parser.type.Constant{:value :user/lastName} #datalog.parser.type.Variable{:symbol ?lname}]}], :qlimit nil, :qoffset nil, :qreturnmaps #datalog.parser.type.ReturnMaps{:mapping-type :keys, :mapping-keys (#datalog.parser.type.MappingKey{:mapping-key foo})}}
'{:find [[?e ?fname]]
:keys [foo]
:in [$ ?fname ?lname]
:where [[?e :user/firstName ?fname]
[?e :user/lastName ?lname]]}
#datalog.parser.type.Query{:qfind #datalog.parser.type.FindTuple{:elements [#datalog.parser.type.Variable{:symbol ?e} #datalog.parser.type.Variable{:symbol ?fname}]}, :qwith nil, :qin [#datalog.parser.type.BindScalar{:variable #datalog.parser.type.SrcVar{:symbol $}} #datalog.parser.type.BindScalar{:variable #datalog.parser.type.Variable{:symbol ?fname}} #datalog.parser.type.BindScalar{:variable #datalog.parser.type.Variable{:symbol ?lname}}], :qwhere [#datalog.parser.type.Pattern{:source #datalog.parser.type.DefaultSrc{}, :pattern [#datalog.parser.type.Variable{:symbol ?e} #datalog.parser.type.Constant{:value :user/firstName} #datalog.parser.type.Variable{:symbol ?fname}]} #datalog.parser.type.Pattern{:source #datalog.parser.type.DefaultSrc{}, :pattern [#datalog.parser.type.Variable{:symbol ?e} #datalog.parser.type.Constant{:value :user/lastName} #datalog.parser.type.Variable{:symbol ?lname}]}], :qlimit nil, :qoffset nil, :qreturnmaps #datalog.parser.type.ReturnMaps{:mapping-type :keys, :mapping-keys (#datalog.parser.type.MappingKey{:mapping-key foo})}}
))
(deftest validation-fails
(are [q msg] (thrown-msg? msg (parser/parse q))
'[:find ?e :where [?x]]
"Query for unknown vars: [?e]"
'[:find ?e :with ?f :where [?e]]
"Query for unknown vars: [?f]"
'[:find ?e ?x ?t :in ?x :where [?e]]
"Query for unknown vars: [?t]"
'[:find ?x ?e :with ?y ?e :where [?x ?e ?y]]
":find and :with should not use same variables: [?e]"
'[:find ?e :in $ $ ?x :where [?e]]
"Vars used in :in should be distinct"
'[:find ?e :in ?x $ ?x :where [?e]]
"Vars used in :in should be distinct"
'[:find ?e :in $ % ?x % :where [?e]]
"Vars used in :in should be distinct"
'[:find ?n :with ?e ?f ?e :where [?e ?f ?n]]
"Vars used in :with should be distinct"
'[:find ?x :where [$1 ?x]]
"Where uses unknown source vars: [$1]"
'[:find ?x :in $1 :where [$2 ?x]]
"Where uses unknown source vars: [$2]"
'[:find ?e :where (rule ?e)]
"Missing rules var '%' in :in"
'[:find ?e :where [?e] :limit [42]]
"Cannot parse :limit, expected java.lang.Long"
'[:find ?e :where [?e] :offset [666]]
"Cannot parse :offset, expected java.lang.Long"
'[:find ?e :keys foo bar :where [?e] :offset 666]
"Count of :keys/:strs/:syms must match count of :find"
'[:find ?e ?f :keys foo :where [?e ?f] :offset 666]
"Count of :keys/:strs/:syms must match count of :find"
'[:find [?e ?f] :keys foo bar :where [?e ?f] :offset 666]
"Count of :keys/:strs/:syms must match count of :find"
'[:find ?e :strs '(foo bar) :keys '("foo" "bar") :where [?e] :offset 666]
"Only one of these three options is allowed: :keys :strs :syms"))

View file

@ -0,0 +1,25 @@
(ns datalog.unparser-test
(:require [datalog.unparser :refer [unparse]]
[datalog.parser :refer [parse]]
[clojure.test :refer [deftest testing is] :as test])
(:use [datalog.unparser]))
(let [q '[:find (sum ?balance-before) ?balance-before
:in $before $after $txn $txs
:where
[(= ?balance-before 42)]]]
(deftest unparse-roundtrip-test
(testing "Datahike query unparsing."
(is (= q (unparse (parse q)))))))
(comment ;; TODO
(let [q '[:find ?foo ?baz
:in $before $after
:where
[(= ?balance-before 42)]
(not [?foo :bar ?baz])]]
(deftest unparse-roundtrip-test
(testing "Datahike query unparsing."
(is (= q (unparse (parse q))))))))

View file

@ -0,0 +1,88 @@
(ns docopt.core-test
(:require [cheshire.core :as json]
[clojure.string :as s]
[clojure.test :refer :all]
[docopt.core :as d]
[docopt.match :as m]))
(def doc-block-regex
(let [doc-begin "r\\\"{3}"
doc-body "((?:\\\"{0,2}[^\\\"]+)*)"
separator "\\\"{3}\n+"
tests "((?:[^r]|r(?!\\\"{3}))*)"]
(re-pattern (str doc-begin doc-body separator tests))))
(def test-block-regex
(let [input-begin "(?:\\A|\\n+)\\s*\\$\\s*prog"
input-body "(.*)"
separator "\\n"
tests "((?:.+\\n)*)"]
(re-pattern (str input-begin input-body separator tests))))
(defn load-test-cases
"Loads language-agnostic docopt tests from file (such as testcases.docopt)."
[path]
(into [] (mapcat (fn [[_ doc tests]]
(map (fn [[_ args result]]
[doc (into [] (filter seq (s/split (or args "") #"\s+"))) (json/parse-string result)])
(re-seq test-block-regex tests)))
(re-seq doc-block-regex (s/replace (slurp path) #"#.*" "")))))
(defn test-case-error-report
"Returns a report of all failed test cases"
[doc in out]
(let [docinfo (try (d/parse doc)
(catch Exception e (.getMessage e)))]
(if (string? docinfo)
(str "\n" (s/trim-newline doc) "\n" docinfo)
(let [result (or (m/match-argv docinfo in) "user-error")]
(when (not= result out)
(str "\n" (s/trim-newline doc)
"\n$ prog " (s/join " " in)
"\nexpected: " (json/generate-string out)
"\nobtained: " (json/generate-string result) "\n\n"))))))
(defn valid?
"Validates all test cases found in the file named 'test-cases-file-name'."
[test-cases-file-name]
(let [test-cases (load-test-cases test-cases-file-name)]
(when-let [eseq (seq (remove nil? (map (partial apply test-case-error-report) test-cases)))]
(println "Failed" (count eseq) "/" (count test-cases) "tests loaded from '" test-cases-file-name "'.\n")
(throw (Exception. (apply str eseq))))
(println "Successfully passed" (count test-cases) "tests loaded from '" test-cases-file-name "'.\n")
true))
(deftest docopt-test
(testing "2-arity version"
(is (= {"<foo>" "a"}
(d/docopt "usage: prog <foo>" ["a"]))))
(testing "3-arity version"
(is (= "a"
(d/docopt "usage: prog <foo>" ["a"] #(get % "<foo>")))))
(testing "4-arity version"
(is (= "usage: prog <foo>"
(d/docopt "usage: prog <foo>" [] identity identity))))
;; Adding this test here since it seems testcases file doesn't support quoted args
(testing "should parse quoted args correctly"
(is (= {"-f" "a b"}
(d/docopt "usage: prog [options]\noptions: -f <foo>" ["-f" "a b"])))
(is (= {"--foo" "a\nb"}
(d/docopt "usage: prog [options]\noptions: --foo <foo>" ["--foo" "a\nb"])))
(is (= {"<foo>" "a b c "}
(d/docopt "usage: prog <foo>" ["a b c "])))
(is (= {"<foo>" "a\tb\nc"}
(d/docopt "usage: prog <foo>" ["a\tb\nc"])))
(binding [docopt.match/*sep-table* {\ "FOO"
\newline "BAR"
\tab "QUX"
\backspace "QUZ"}]
(is (= {"<foo>" "a b\nc\td\b"}
(d/docopt "usage: prog <foo>" ["aFOObBARcQUXdQUZ"]))))))
(deftest language-agnostic-test
(is (valid? "https://raw.github.com/docopt/docopt/511d1c57b59cd2ed663a9f9e181b5160ce97e728/testcases.docopt"))
;; BB-TEST-PATCH: Modified test path
(is (valid? "test-resources/lib_tests/docopt/extra_testcases.docopt")))

Some files were not shown because too many files have changed in this diff Show more