From da5134795e29fee12ba935eff6df9e427db913ef Mon Sep 17 00:00:00 2001
From: Adar Nimrod <nimrod@shore.co.il>
Date: Wed, 9 Aug 2017 18:41:02 +0300
Subject: [PATCH] - Updated pre-commit hooks. - Changed tests to use Bats,
 updated README. - Removed dependency on Make, updated README, TravisCI. -
 Added usage when called after sourced. - Cleaner is_sourced alias. - No
 longer cd into the certs directory. - Fixed several small issues, bugs and
 edge cases.

---
 .pre-commit-config.yaml             |  9 +---
 .travis.yml                         |  4 +-
 README.rst                          | 13 ++---
 bundle_certs                        | 33 +++++++------
 Makefile => tests/bundle-certs.bats | 73 +++++++++++------------------
 5 files changed, 56 insertions(+), 76 deletions(-)
 rename Makefile => tests/bundle-certs.bats (51%)

diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml
index 8569f91..505e74e 100644
--- a/.pre-commit-config.yaml
+++ b/.pre-commit-config.yaml
@@ -1,5 +1,5 @@
 -   repo: git://github.com/pre-commit/pre-commit-hooks
-    sha: v0.7.1
+    sha: v0.9.1
     hooks:
     -   id: check-added-large-files
     -   id: check-merge-conflict
@@ -10,10 +10,3 @@
         files: bundle_certs
     -   id: shellcheck
         files: bundle_certs
--   repo: local
-    hooks:
-    -   id: test
-        name: make test
-        language: system
-        entry: make test test_source
-        files: bundle_certs|Makefile
diff --git a/.travis.yml b/.travis.yml
index 7b519b7..7c84a26 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -17,7 +17,6 @@ addons:
       - mawk
       - openssl
       - curl
-      - build-essential
       - cabal-install
       - ghc
 
@@ -29,7 +28,8 @@ install:
   - pip install pre_commit | cat
 
 script:
-  - pre-commit run --all-files
+    - pre-commit run --all-files
+    - bats --tap tests/
 
 notifications:
   on_failure: never
diff --git a/README.rst b/README.rst
index 2e1a21e..da4ec74 100644
--- a/README.rst
+++ b/README.rst
@@ -28,8 +28,9 @@ For regular use:
 
 For testing/ development purposes, all of the above, plus:
 
-- Make.
 - Curl.
+- `Bats <https://github.com/sstephenson/bats>`_.
+- `Pre-commit <http://pre-commit.com/>`_.
 
 Usage
 -----
@@ -58,12 +59,12 @@ Shell functions
   subject hash).
 - bundle_certs: See Usage section above.
 
-Development
------------
+Development and testing
+-----------------------
 
-For testing run :code:`make test`. For cleaning temporary files run :code:`git
-clean -fdx`. You can use `pre-commit <http://pre-commit.com/>`_ to have the test
-(which is quite quick) run on every commit to ensure quality code.
+Testing is done using Bats <https://github.com/sstephenson/bats>`_. To test run
+:code:`bats --tap tests/`. `Pre-commit <http://pre-commit.com/>`_ is also
+configured for this repo.
 
 License
 -------
diff --git a/bundle_certs b/bundle_certs
index 19d6480..206642b 100755
--- a/bundle_certs
+++ b/bundle_certs
@@ -3,7 +3,7 @@
 
 # Check if the script is being sourced or not.
 # shellcheck disable=SC2142
-alias is_sourced='[ "$_" != "$0" ] && expr "$-" : ".*i.*" > /dev/null'
+alias is_sourced='[ "$_" != "$0" ] && [ "${-#*i}" != "$-" ]'
 
 # Returns the subject hash of the certificate path provided.
 alias subject_hash='openssl x509 -noout -subject_hash -in'
@@ -61,38 +61,41 @@ unbundle_cert () {
 }
 
 bundle_certs () {
-    local issuer issued ordered_certs filename
+    local filename issuer issued bundle
+    if [ $# -eq 0 ]
+    then
+        echo "Usage: bundle_certs filename [filename2 [filename3 ...]]" >> /dev/stderr
+        return 1
+    fi
     for filename in "$@"
     do
         [ -f "$filename" ] && unbundle_cert "$filename"
     done
-    cd certs
-    issuer="$(find_root_cert "*")"
+    issuer="$(find_root_cert certs/*)"
     if [ -z "$issuer" ]
     then
-        echo "Failed to find root certificate." > /dev/stderr
-        exit 1
+        echo "Failed to find root certificate." >> /dev/stderr
+        return 1
     fi
-    issued="$(find_cert_by_issuer_hash "$issuer" "*")"
+    issued="$(find_cert_by_issuer_hash "$(basename "$issuer")" certs/*)"
+    bundle="$(cat "$issued")"
     while [ -n "$issued" ]
     do
-        ordered_certs="$issued $ordered_certs"
         issuer="$issued"
-        issued="$(find_cert_by_issuer_hash "$issuer" "*")"
+        issued="$(find_cert_by_issuer_hash "$(basename "$issuer")" certs/*)"
+        [ -n "$issued" ] && bundle="$(echo "${bundle:-}"; cat "$issued")"
     done
-    cat "$ordered_certs"
-    cd ..
+    echo "$bundle"
     rm -r certs
 }
 
-
-if ! is_sourced
+if ! (is_sourced)
 then
     set -eu
     if [ $# -eq 0 ]
     then
-        echo "Usage: $0 filename [filename2 [filename3 ...]]" > /dev/stderr
-        exit 1
+        echo "Usage: $(basename "$0") filename [filename2 [filename3 ...]]" >> /dev/stderr
+        return 1
     else
         bundle_certs "$@"
     fi
diff --git a/Makefile b/tests/bundle-certs.bats
similarity index 51%
rename from Makefile
rename to tests/bundle-certs.bats
index 8015254..9401ebb 100644
--- a/Makefile
+++ b/tests/bundle-certs.bats
@@ -1,59 +1,42 @@
-.PHONY: test clean
+#!/usr/bin/env bats
 
-.testcerts:
-	mkdir -p .testcerts
-
-.testcerts/serial: .testcerts
+setup () {
+    teardown
+    mkdir -p .testcerts
 	echo 1000 > .testcerts/serial
-
-.testcerts/root.key: .testcerts
 	openssl genrsa -out .testcerts/root.key 4096
-
-.testcerts/root.crt: .testcerts/root.key
 	openssl req -new -x509 -days 7 -key .testcerts/root.key -nodes -out .testcerts/root.crt -subj /C=US/ST=State/L=City/O=RootCA/OU=Unit/CN=localhost/emailAddress=none@nowhere.com
-
-.testcerts/intermediate1.key: .testcerts
 	openssl genrsa -out .testcerts/intermediate1.key 4096
-
-.testcerts/intermediate1.csr: .testcerts/intermediate1.key
 	openssl req -new -key .testcerts/intermediate1.key -out .testcerts/intermediate1.csr -subj /C=US/ST=State/L=City/O=FirstIntermediate/OU=Unit/CN=localhost/emailAddress=none@nowhere.com
-
-.testcerts/intermediate1.crt: .testcerts/intermediate1.csr .testcerts/root.key .testcerts/root.crt .testcerts/serial
 	openssl x509 -req -days 7 -in .testcerts/intermediate1.csr -out .testcerts/intermediate1.crt -CAkey .testcerts/root.key -CA .testcerts/root.crt -CAserial .testcerts/serial
-
-.testcerts/intermediate2.key: .testcerts
 	openssl genrsa -out .testcerts/intermediate2.key 4096
-
-.testcerts/intermediate2.csr: .testcerts/intermediate2.key
 	openssl req -new -key .testcerts/intermediate2.key -out .testcerts/intermediate2.csr -subj /C=US/ST=State/L=City/O=SecondIntermediate/OU=Unit/CN=localhost/emailAddress=none@nowhere.com
-
-.testcerts/intermediate2.crt: .testcerts/intermediate2.csr .testcerts/intermediate1.key .testcerts/serial .testcerts/intermediate1.crt
 	openssl x509 -req -days 7 -in .testcerts/intermediate2.csr -out .testcerts/intermediate2.crt -CAkey .testcerts/intermediate1.key -CA .testcerts/intermediate1.crt -CAserial .testcerts/serial
-
-.testcerts/server.key: .testcerts
 	openssl genrsa -out .testcerts/server.key 4096
-
-.testcerts/server.csr: .testcerts/server.key
 	openssl req -new -key .testcerts/server.key -out .testcerts/server.csr -subj /C=US/ST=State/L=City/O=Server/OU=Unit/CN=localhost/emailAddress=none@nowhere.com
-	
-.testcerts/server.crt: .testcerts/intermediate2.key .testcerts/server.csr .testcerts/serial .testcerts/intermediate2.crt
 	openssl x509 -req -days 7 -in .testcerts/server.csr -out .testcerts/server.crt -CAkey .testcerts/intermediate2.key -CA .testcerts/intermediate2.crt -CAserial .testcerts/serial
-	
-.testcerts/intermediates.crt: .testcerts/intermediate1.crt .testcerts/intermediate2.crt
 	cat .testcerts/intermediate1.crt .testcerts/intermediate2.crt > .testcerts/intermediates.crt
-
-.testcerts/bundle.crt: .testcerts/intermediates.crt .testcerts/server.crt
-	./bundle_certs .testcerts/* > .testcerts/bundle.crt
-
-test: .testcerts/bundle.crt .testcerts/root.crt .testcerts/server.key
-	openssl s_server -cert .testcerts/bundle.crt -key .testcerts/server.key -quiet -www -no_dhe & echo "$$!" > .server.pid
-	test "$$(curl --fail --cacert .testcerts/root.crt --write-out '%{ssl_verify_result}' --silent --output /dev/null https://localhost:4433)" = "0"
-	if [ -f .server.pid ] && [ -d "/proc/$$(cat .server.pid)" ]; then kill "$$(cat .server.pid)"; fi
-	rm -f .server.pid
-
-clean:
-	- kill "$$(cat .server.pid)"
-	git clean -fdx
-
-test_source:
-	/bin/sh -c '. ./bundle_certs'
+}
+
+teardown () {
+    [ -f .server.pid ] && [ -d "/proc/$$(cat .server.pid)" ] && kill "$(cat .server.pid)" || true
+    #git clean -fdX
+}
+
+server_test () {
+	openssl s_server -cert .testcerts/bundle.crt -key .testcerts/server.key -quiet -www -no_dhe &
+    echo "$!" > .server.pid
+	run curl --fail --cacert .testcerts/root.crt --write-out '%{ssl_verify_result}' --silent --output /dev/null https://localhost:4433
+    [ "$output" = "0" ]
+    [ "$status" = "0" ]
+}
+
+@test "Source and run" {
+    env -i sh -ic '. ./bundle_certs && bundle_certs .testcerts/* > .testcerts/bundle.crt'
+    server_test
+}
+
+@test "Run" {
+    ./bundle_certs .testcerts/* > .testcerts/bundle.crt
+    server_test
+}
-- 
GitLab