├── LICENSE ├── README.md ├── sharnessify.sh └── templates ├── Makefile └── install-sharness.sh /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2015 Christian Couder 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in 13 | all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | THE SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Sharnessify 2 | 3 | Sharnessify contains scripts to easily add Sharness infrastructure to 4 | a project. 5 | 6 | ## Purpose and Goal 7 | 8 | [Sharness](https://github.com/chriscool/sharness/) is a great test 9 | framework written in Shell. It is actively developed and comes from 10 | Git itself. 11 | 12 | Although you can embed Sharness files into your project, it is not so 13 | easy to do it cleanly while making it possible to update these 14 | Sharness files. Also some people don't want to mix the GPLv2 Sharness 15 | files with their own files that are licensed differently. 16 | 17 | That's why the goal of this project is to make it easy to cleanly 18 | install Sharness support, so that Sharness files are separated from 19 | other files and can easily be installed and updated. 20 | 21 | ## Usage 22 | 23 | Clone this repo to a temporary directory and run `sharnessify.sh` with the path 24 | to your project: 25 | 26 | ```sh 27 | $ cd ~/dev/my-project 28 | 29 | $ git clone git://github.com/chriscool/sharnessify /tmp/sharnessify 30 | 31 | $ /tmp/sharnessify/sharnessify.sh . 32 | 33 | $ git status 34 | Changes to be committed: 35 | (use "git reset HEAD ..." to unstage) 36 | 37 | new file: sharness/.gitignore 38 | new file: sharness/Makefile 39 | new file: sharness/lib/install-sharness.sh 40 | new file: sharness/t0000-sharness.sh 41 | ``` 42 | 43 | Now run `git commit` and your project is equipped with sharness! 44 | 45 | ## How it works 46 | 47 | The `sharnessify.sh` script adds a Sharness install and update script 48 | called `install-sharness.sh` and then runs it to install Sharness. A 49 | `.gitignore` to ignore Sharness, a sample Sharness test script called 50 | `t0000-sharness.sh` and a `Makefile` to run all the Sharness tests are 51 | also added. 52 | 53 | The `sharnessify.sh` script accepts an optional directory as 54 | argument. Passing no argument is like passing `.`, that is the current 55 | directory from which `sharnessify.sh` is run. This directory is where 56 | the `sharness` directory will be created. And `sharnessify.sh` will 57 | put everything it creates or fetches in this `sharness` directory. 58 | 59 | This `sharness` directory will contain the following: 60 | 61 | * `Makefile`: to run Sharness tests using simply `make` 62 | 63 | * `t0000-sharness.sh`: a sample Sharness test, just to check that 64 | Sharness itself is working 65 | 66 | * `lib` a directory that itself contains: 67 | 68 | - `install-sharness.sh`: a script to install and update Sharness 69 | 70 | - `sharness`: a directory where Sharness is cloned and updated 71 | 72 | * `.gitignore`: a Git config file to tell Git to ignore 73 | `lib/sharness`, the directory where Sharness is cloned, and also the 74 | directories where Sharness runs the tests and stores their results 75 | 76 | The above files that are not in the `sharness/lib/sharness` directory 77 | are all MIT licensed, so it should not be a problem to add them to 78 | your project. The `sharnessify.sh` script will perform a `git add` on 79 | them, but will not `git commit` them. You should do that though to 80 | finish the sharnessification. 81 | 82 | ## Updating Sharness 83 | 84 | When the `install-sharness.sh` script is copied, the Sharness version 85 | that this script should install is specified in the `version` variable 86 | at the top of the `install-sharness.sh` script. This `version` 87 | variable is set to the SHA1, also called object id, of the last Git 88 | commit in the Sharness repository used to clone Sharness. 89 | 90 | By default the Sharness repository used to clone Sharness is the 91 | cannonical repository from GitHub 92 | (https://github.com/chriscool/sharness.git). But you can use a local 93 | repository instead by passing the `-l `, or `--local `, 94 | option to `sharnessify.sh`. If you do that then this `` 95 | repository will also be used by `install-sharness.sh`, as it will be 96 | specified in the `urlprefix` variable at the top of 97 | `install-sharness.sh`. 98 | 99 | So if you want to update Sharness, you only need to change the 100 | `version`, and maybe also the `urlprefix` variables at the top of 101 | `install-sharness.sh`. As the `Makefile` calls `install-sharness.sh` 102 | before running the test scripts, Sharness will be updated the next 103 | time the tests are run. Or you can update Sharness by directly running 104 | `install-sharness.sh`. 105 | -------------------------------------------------------------------------------- /sharnessify.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # 3 | # Copyright (c) 2015 Christian Couder 4 | # MIT Licensed; see the LICENSE file in this repository. 5 | # 6 | # Script to add sharness infrastructure to a project 7 | 8 | SHARNESS_URL="https://github.com/chriscool/sharness.git" 9 | LIB_BASE_DIR="lib" 10 | SHARNESS_BASE_DIR="sharness" 11 | INSTALL_NAME="install-sharness.sh" 12 | MAKEFILE_NAME="Makefile" 13 | 14 | USAGE="$0 [-h] [-v] [-l ] []" 15 | 16 | usage() { 17 | echo "$USAGE" 18 | echo " Add sharness infrastructure to a project" 19 | echo " Options:" 20 | echo " -h|--help: print this usage message and exit" 21 | echo " -v|--verbose: print logs of what happens" 22 | echo " -l|--local: use local Sharness repo to clone from" 23 | exit 0 24 | } 25 | 26 | die() { 27 | echo >&2 "fatal: $@" 28 | exit 1 29 | } 30 | 31 | log() { 32 | test -z "$VERBOSE" || echo "->" "$@" 33 | } 34 | 35 | PROJ_DIR="" 36 | VERBOSE="" 37 | 38 | # get user options 39 | while [ "$#" -gt "0" ]; do 40 | # get options 41 | arg="$1" 42 | shift 43 | 44 | case "$arg" in 45 | -h|--help) 46 | usage ;; 47 | -v|--verbose) 48 | VERBOSE=1 ;; 49 | -l|--local) 50 | SHARNESS_URL="$(cd "$1" && pwd)" || die "could not cd into '$1'" 51 | shift 52 | test -n "$SHARNESS_URL" || die "invalid Sharness URL '$SHARNESS_URL'" 53 | log "SHARNESS_URL is now set to '$SHARNESS_URL'" 54 | ;; 55 | -*) 56 | die "unrecognised option: '$arg'\n$USAGE" ;; 57 | *) 58 | test -z "$PROJ_DIR" || die "too many arguments\n$USAGE" 59 | PROJ_DIR="$arg" 60 | ;; 61 | esac 62 | done 63 | 64 | # Setup PROJ_DIR properly 65 | test -n "$PROJ_DIR" || PROJ_DIR="." 66 | log "PROJ_DIR is set to '$PROJ_DIR'" 67 | test -d "$PROJ_DIR" || echo >&2 "warning: '$PROJ_DIR' will be created" 68 | 69 | # Get the directory that contains this script 70 | PARENT_DIR=$(cd "$(dirname "$0")" && pwd) || 71 | die "could not get script parent directory from '$0'" 72 | TEMPLATE_DIR="$PARENT_DIR/templates" 73 | TEMPLATE_INSTALL="$TEMPLATE_DIR/$INSTALL_NAME" 74 | TEMPLATE_MAKEFILE="$TEMPLATE_DIR/$MAKEFILE_NAME" 75 | log "This script's parent directory is '$PARENT_DIR'" 76 | 77 | # Create sharness directories 78 | SHARNESS_DIR="$PROJ_DIR/$SHARNESS_BASE_DIR" 79 | SHARNESS_LIB_DIR="$SHARNESS_DIR/$LIB_BASE_DIR" 80 | mkdir -p "$SHARNESS_LIB_DIR" || 81 | die "could not create '$SHARNESS_LIB_DIR' directory" 82 | log "SHARNESS_LIB_DIR ($SHARNESS_LIB_DIR) is ready" 83 | 84 | # Copy sharness install script 85 | cp "$TEMPLATE_INSTALL" "$SHARNESS_LIB_DIR/" || 86 | die "could not copy '$TEMPLATE_INSTALL' into '$SHARNESS_LIB_DIR/'" 87 | INSTALL_SCRIPT="$SHARNESS_LIB_DIR/$INSTALL_NAME" 88 | log "INSTALL_SCRIPT ($INSTALL_SCRIPT) has been copied from '$TEMPLATE_DIR'" 89 | 90 | # Create temp directory 91 | DATE=$(date +"%Y-%m-%dT%H:%M:%SZ") 92 | TMPDIR=$(mktemp -d "/tmp/sharnessify.$DATE.XXXXXX") || 93 | die "could not 'mktemp -d /tmp/sharnessify.$DATE.XXXXXX'" 94 | log "TMPDIR ($TMPDIR) created" 95 | 96 | # Clone Sharness 97 | ( 98 | cd "$TMPDIR" || die "could not cd into '$TMPDIR'" 99 | git clone "$SHARNESS_URL" || 100 | die "could not clone from '$SHARNESS_URL'" 101 | ) || exit 102 | log "Sharness cloned from '$SHARNESS_URL'" 103 | 104 | # Get Sharness version 105 | SHARNESS_VERSION=$(cd "$TMPDIR/sharness" && git rev-parse HEAD) 106 | test -n "$SHARNESS_VERSION" || 107 | die "could not get Sharness version from repo in '$TMPDIR/sharness'" 108 | log "SHARNESS_VERSION is set to '$SHARNESS_VERSION'" 109 | 110 | # Substitute variables in install script 111 | ESCAPED_URL=$(echo "$SHARNESS_URL" | sed -e 's/[\/&]/\\&/g') 112 | sed -i "s/XXX_SHARNESSIFY_VERSION_XXX/$SHARNESS_VERSION/" "$INSTALL_SCRIPT" || 113 | die "could not modify '$INSTALL_SCRIPT'" 114 | sed -i "s/XXX_SHARNESSIFY_URL_XXX/$ESCAPED_URL/" "$INSTALL_SCRIPT" || 115 | die "could not modify '$INSTALL_SCRIPT'" 116 | sed -i "s/XXX_SHARNESSIFY_LIB_XXX/$LIB_BASE_DIR/" "$INSTALL_SCRIPT" || 117 | die "could not modify '$INSTALL_SCRIPT'" 118 | sed -i "s/XXX_SHARNESSIFY_SHARNESS_XXX/sharness/" "$INSTALL_SCRIPT" || 119 | die "could not modify '$INSTALL_SCRIPT'" 120 | log "Variables substituted in '$INSTALL_SCRIPT'" 121 | 122 | # Add .gitignore 123 | GIT_IGNORE="$SHARNESS_DIR/.gitignore" 124 | echo "$LIB_BASE_DIR/$SHARNESS_BASE_DIR/" >"$GIT_IGNORE" 125 | echo "test-results/" >>"$GIT_IGNORE" 126 | echo "trash directory.*.sh/" >>"$GIT_IGNORE" 127 | log "'$GIT_IGNORE' created" 128 | 129 | # Run install script 130 | ( 131 | cd "$SHARNESS_DIR" || die "could not cd into '$SHARNESS_DIR'" 132 | "$LIB_BASE_DIR/$INSTALL_NAME" || die "installation script '$INSTALL_SCRIPT' failed" 133 | ) || exit 134 | log "INSTALL_SCRIPT ($INSTALL_SCRIPT) ran in '$SHARNESS_DIR'" 135 | 136 | # Copy a simple test into the test directory 137 | SIMPLE_TEST_ORIG="$TMPDIR/sharness/test/simple.t" 138 | SIMPLE_TEST_DEST="$SHARNESS_DIR/t0000-sharness.sh" 139 | SHARNESS_TEST_LIB="$LIB_BASE_DIR/$SHARNESS_BASE_DIR/sharness.sh" 140 | ESCAPED_TEST_LIB=$(echo "$SHARNESS_TEST_LIB" | sed -e 's/[\/&]/\\&/g') 141 | cp "$SIMPLE_TEST_ORIG" "$SIMPLE_TEST_DEST" || 142 | die "could not copy '$SIMPLE_TEST_ORIG' to '$SIMPLE_TEST_DEST'" 143 | sed -i "s/. .\/sharness.sh/. .\/$ESCAPED_TEST_LIB/" "$SIMPLE_TEST_DEST" || 144 | die "could not modify '$SIMPLE_TEST_DEST'" 145 | log "Simple test ($SIMPLE_TEST_DEST) created" 146 | 147 | # Cleanup temp directory 148 | rm -rf "$TMPDIR" 149 | 150 | # Copy Makefile 151 | cp "$TEMPLATE_MAKEFILE" "$SHARNESS_DIR/" || 152 | die "could not copy '$TEMPLATE_MAKEFILE' into '$SHARNESS_DIR/'" 153 | MAKEFILE_SCRIPT="$SHARNESS_DIR/$MAKEFILE_NAME" 154 | log "MAKEFILE_SCRIPT ($MAKEFILE_SCRIPT) has been copied from '$TEMPLATE_DIR'" 155 | 156 | # Substitute variables in Makefile 157 | sed -i "s/XXX_SHARNESSIFY_LIB_XXX/$LIB_BASE_DIR/" "$MAKEFILE_SCRIPT" || 158 | die "could not modify '$MAKEFILE_SCRIPT'" 159 | sed -i "s/XXX_SHARNESSIFY_SHARNESS_XXX/sharness/" "$MAKEFILE_SCRIPT" || 160 | die "could not modify '$MAKEFILE_SCRIPT'" 161 | log "Variables substituted in '$MAKEFILE_SCRIPT'" 162 | 163 | # Run make to verify that everything works 164 | ( 165 | cd "$SHARNESS_DIR" || die "could not cd into '$SHARNESS_DIR'" 166 | make || die "make failed in '$SHARNESS_DIR'" 167 | ) || exit 168 | log "'make' ran in '$SHARNESS_DIR'" 169 | 170 | # Add everything into Git 171 | git add "$GIT_IGNORE" "$MAKEFILE_SCRIPT" "$INSTALL_SCRIPT" "$SIMPLE_TEST_DEST" || 172 | die "could not add Sharness support files into Git" 173 | log "'git add'ed Sharness support files" 174 | 175 | echo "**************" 176 | echo "* SUCCESS!!! *" 177 | echo "**************" 178 | echo 179 | echo "You can now commit the generated support files into Git using for example:" 180 | echo 181 | echo " git commit -m 'Add Sharness support files'" 182 | echo 183 | -------------------------------------------------------------------------------- /templates/Makefile: -------------------------------------------------------------------------------- 1 | # Run sharness tests 2 | # 3 | # Copyright (c) 2014 Christian Couder 4 | # MIT Licensed; see the LICENSE file in this repository. 5 | # 6 | # NOTE: run with TEST_VERBOSE=1 for verbose sharness tests. 7 | 8 | T = $(sort $(wildcard t[0-9][0-9][0-9][0-9]-*.sh)) 9 | LIBDIR = XXX_SHARNESSIFY_LIB_XXX 10 | SHARNESSDIR = XXX_SHARNESSIFY_SHARNESS_XXX 11 | AGGREGATE = $(LIBDIR)/$(SHARNESSDIR)/aggregate-results.sh 12 | 13 | 14 | # Add below the binaries that this project generates or needs. 15 | # For example: 16 | # BINS = bin/ipfs 17 | BINS = 18 | 19 | all: aggregate 20 | 21 | clean: clean-test-results 22 | @echo "*** $@ ***" 23 | # Clean binaries below. 24 | # For example: 25 | # -rm -rf bin/ipfs 26 | 27 | clean-test-results: 28 | @echo "*** $@ ***" 29 | -rm -rf test-results 30 | 31 | $(T): clean-test-results deps 32 | @echo "*** $@ ***" 33 | ./$@ 34 | 35 | aggregate: clean-test-results $(T) 36 | @echo "*** $@ ***" 37 | ls test-results/t*-*.sh.*.counts | $(AGGREGATE) 38 | 39 | # Add below some needed dependencies. 40 | # For example: 41 | # deps: sharness $(BINS) curl 42 | deps: sharness $(BINS) 43 | 44 | sharness: 45 | @echo "*** checking $@ ***" 46 | lib/install-sharness.sh 47 | 48 | # Add below other targets like: 49 | # - the targets needed to build binaries, 50 | # - targets using special compile flags, 51 | # - targets to check or install dependencies. 52 | # 53 | # For example: 54 | # 55 | # GOFLAGS = 56 | # 57 | # bin/%: FORCE 58 | # cd .. && make GOFLAGS=$(GOFLAGS) $@ 59 | # 60 | # race: 61 | # make GOFLAGS=-race all 62 | # 63 | # curl: 64 | # @which curl >/dev/null || (echo "Please install curl!" && false) 65 | 66 | .PHONY: all clean clean-test-results $(T) aggregate deps sharness FORCE 67 | 68 | -------------------------------------------------------------------------------- /templates/install-sharness.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # install-sharness.sh 3 | # 4 | # Copyright (c) 2014 Juan Batiz-Benet 5 | # Copyright (c) 2015 Christian Couder 6 | # MIT Licensed; see the LICENSE file in this repository. 7 | # 8 | # This script checks that Sharness is installed in: 9 | # 10 | # $(pwd)/$clonedir/$sharnessdir/ 11 | # 12 | # where $clonedir and $sharnessdir are configured below. 13 | # 14 | # If Sharness is not installed, this script will clone it 15 | # from $urlprefix (defined below). 16 | # 17 | # If Sharness is not uptodate with $version (defined below), 18 | # this script will fetch and will update the installed 19 | # version to $version. 20 | # 21 | 22 | # settings 23 | version=XXX_SHARNESSIFY_VERSION_XXX 24 | urlprefix=XXX_SHARNESSIFY_URL_XXX 25 | clonedir=XXX_SHARNESSIFY_LIB_XXX 26 | sharnessdir=XXX_SHARNESSIFY_SHARNESS_XXX 27 | 28 | if test -f "$clonedir/$sharnessdir/SHARNESS_VERSION_$version" 29 | then 30 | # There is the right version file. Great, we are done! 31 | exit 0 32 | fi 33 | 34 | die() { 35 | echo >&2 "$@" 36 | exit 1 37 | } 38 | 39 | checkout_version() { 40 | git checkout "$version" || die "Could not checkout '$version'" 41 | rm -f SHARNESS_VERSION_* || die "Could not remove 'SHARNESS_VERSION_*'" 42 | touch "SHARNESS_VERSION_$version" || die "Could not create 'SHARNESS_VERSION_$version'" 43 | echo "Sharness version $version is checked out!" 44 | } 45 | 46 | if test -d "$clonedir/$sharnessdir/.git" 47 | then 48 | # We need to update sharness! 49 | cd "$clonedir/$sharnessdir" || die "Could not cd into '$clonedir/$sharnessdir' directory" 50 | git fetch || die "Could not fetch to update sharness" 51 | else 52 | # We need to clone sharness! 53 | mkdir -p "$clonedir" || die "Could not create '$clonedir' directory" 54 | cd "$clonedir" || die "Could not cd into '$clonedir' directory" 55 | 56 | git clone "$urlprefix" || die "Could not clone '$urlprefix'" 57 | cd "$sharnessdir" || die "Could not cd into '$sharnessdir' directory" 58 | fi 59 | 60 | checkout_version 61 | --------------------------------------------------------------------------------