#!/bin/sh

. ./realpath.sh

setUp() {
    _test_previousdir=$PWD
    _test_workingdir=$(mktemp -d -t sh-realpath.XXXXXX)
    cd -P -- "$_test_workingdir"
}

tearDown() {
    cd -- "$_test_previousdir"
    rm -rf -- "$_test_workingdir"
}

it_outputs_pwd_when_passed_zero_args() {
    local output

    output=$(canonicalize_path)

    assertTrue '`canonicalize_path` succeeds' $?
    assertEquals 'outputs $PWD' "$PWD/" "$output"
}

it_outputs_absolute_path_to_target_when_passed_the_name_of_a_non_existent_file() {
    local output

    output=$(canonicalize_path non_existent_file)

    assertTrue '`canonicalize_path non_existent_file` succeeds' $?
    assertEquals 'output is "$PWD/non_existent_file"' "$PWD/non_existent_file" "$output"
}

it_returns_an_error_when_passed_a_path_in_a_non_existent_dir() {
    local output

    output=$(canonicalize_path non_existent_dir/somepath 2>&1)

    assertFalse '`canonicalize_path non_existent_dir/somepath` fails' $?
    assertNull 'no output' "$output"
}

it_outputs_absolute_path_when_passed_the_name_of_a_path_in_a_subdir() {
    local output
    mkdir somedir

    output=$(canonicalize_path somedir/somepath)

    assertTrue '`canonicalize_path somedir/somepath` succeeds' $?
    assertEquals 'output is "$PWD/somedir/somepath"' "$PWD/somedir/somepath" "$output"
}

it_returns_an_error_when_passed_a_path_in_a_symlink_to_nowhere() {
    ln -s non/existent/dir somelink

    canonicalize_path somelink/somepath

    assertFalse '`canonicalize_path somelink/somepath` fails' $?
}

it_returns_the_target_dir_when_passed_a_symlink_to_another_dir() {
    local output
    mkdir somedir
    ln -s somedir somelink

    output=$(canonicalize_path somelink)

    assertTrue '`canonicalize_path somelink` succeeds' $?
    assertEquals 'output is "$PWD/somedir"' "$PWD/somedir" "$output"
}

it_returns_absolute_path_of_target_directory_when_passed_a_path_in_a_symlink_to_another_dir() {
    local output
    mkdir somedir
    ln -s somedir somelink

    output=$(canonicalize_path somelink/somepath)

    assertTrue '`canonicalize_path somelink/somepath` succeeds' $?
    assertEquals 'output is "$PWD/somedir/somepath"' "$PWD/somedir/somepath" "$output"
}

it_collapses_current_dir_references() {
    local output

    output=$(canonicalize_path ././somepath)

    assertTrue '`canonicalize_path ././somepath` succeeds' $?
    assertEquals 'output is "$PWD/somepath"' "$PWD/somepath" "$output"
}

it_collapses_extra_slashes() {
    local output

    output=$(canonicalize_path .///somepath)

    assertTrue '`canonicalize_path .///somepath` succeeds' $?
    assertEquals 'output is "$PWD/somepath"' "$PWD/somepath" "$output"
}

it_collapses_parent_dir_references() {
    local output
    mkdir -p somedir/anotherdir

    output=$(canonicalize_path somedir/anotherdir/../../somepath)

    assertTrue '`canonicalize_path somedir/anotherdir/../../somepath` succeeds' $?
    assertEquals 'output is "$PWD/somepath"' "$PWD/somepath" "$output"
}


##### Test Harness #####

# suite() -- find and register tests to be run
#   Derived from Gary Bernhardt's screencast #68
#   (https://www.destroyallsoftware.com/screencasts/catalog/test-driving-shell-scripts)
suite() {
    local name tests
    tests=$(grep ^it_ "$0" | cut -d '(' -f 1)
    for name in $tests; do
        suite_addTest "$name"
    done
}

if hash shunit2 2>/dev/null; then
    . shunit2
else
    echo 'Error: shunit2(1) could not be located. Please install it on your $PATH.' >&2
    exit 1
fi
