# -*- coding: utf-8; mode: tcl; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- vim:fenc=utf-8:ft=tcl:et:sw=4:ts=4:sts=4

package require tcltest 2
namespace import tcltest::*

set pwd [file dirname [file normalize $argv0]]

source ../port_test_autoconf.tcl
package require macports 1.0

array set ui_options {}
#set ui_options(ports_debug)   yes
#set ui_options(ports_verbose) yes
mportinit ui_options

package require portlint 1.0

test test_lint_checksum_type_list {
    Verify that we get no warnings if we pass in the list of recommended
    checksum types to lint_checksum_type_list.
} -body {
    set preferred_checksum_types [list rmd160 sha256 size]
    set results [portlint::lint_checksum_type_list $preferred_checksum_types]

    if {[llength $results] > 0} {
        return "FAIL: unexpected results"
    }
    return "lint_checksum_type_list passed"
} -result "lint_checksum_type_list passed"

test test_lint_checksum_type_list_missing_recommended {
    Verify that we are warned about a missing recommended field in the
    list of checksums types passed to lint_checksum_type_list.
} -body {
    set preferred_checksum_types [list rmd160 sha256]
    set results [portlint::lint_checksum_type_list $preferred_checksum_types]

    if {[llength $results] == 0} {
        return "FAIL: unexpected results: no results returned"
    }

    if {[lsearch -regexp $results {size}] ==  -1} {
        return "FAIL: no mention of the missing size field"
    }

    return "lint_checksum_type_list_missing_recommended passed"
} -result "lint_checksum_type_list_missing_recommended passed"

test test_lint_checksum_type_list_deprecated_md5 {
    Verify that we are warned about MD5 being an insecure checksum type
} -body {
    set preferred_checksum_types [list md5]
    set results [portlint::lint_checksum_type_list $preferred_checksum_types]

    if {[llength $results] == 0} {
        return "FAIL: unexpectedly encountered no results"
    }

    if {[lsearch -regexp $results {insecure.+md5}] == -1} {
        return "FAIL: expecting deprecation warning for using MD5 solely"
    }

    if {[lsearch -regexp $results {missing.+recommended}] == -1} {
        return "FAIL: expecting warnings about missing recommended checksum\
                types"
    }

    return "lint_checksum_type_list_deprecated_md5 passed"
} -result "lint_checksum_type_list_deprecated_md5 passed"

test test_lint_checksum_type_list_deprecated_sha1 {
    Verify that we are warned about SHA1 being an insecure checksum type
} -body {
    set preferred_checksum_types [list sha1]
    set results [portlint::lint_checksum_type_list $preferred_checksum_types]

    if {[llength $results] == 0} {
        return "FAIL: unexpected results: no results returned"
    }

    if {[lsearch -regexp $results {insecure.+sha1}] == -1} {
        return "FAIL: no mention of the deprecated sha1 field"
    }

    if {[lsearch -regexp $results {missing.+recommended}] == -1} {
        return "FAIL: expecting warnings about missing recommended checksum\
                types"
    }

    return "lint_checksum_type_list_deprecated_sha1 passed"
} -result "lint_checksum_type_list_deprecated_sha1 passed"

test test_lint_checksum_type_list_mixed {
    Verify that we are warned about a missing recommended field when
    multiple fields are specified
} -body {
    set preferred_checksum_types [list md5 rmd160 sha256]
    set results [portlint::lint_checksum_type_list $preferred_checksum_types]

    if {[llength $results] == 0} {
        return "FAIL: unexpected results: no results returned"
    }

    if {[lsearch -regexp $results {missing.+size}] == -1} {
        return "FAIL: no mention of missing recommended size field: $results"
    }

    return "lint_checksum_type_list_mixed passed"
} -result "lint_checksum_type_list_mixed passed"

test test_lint_checksum_basic {
    Verify linting the most basic checksum that is still valid
} -body {
    set checksum "checksum size 1"

    set results [portlint::lint_checksum $checksum]

    if {[llength $results] == 0} {
        return "FAIL: invalid results returned: empty list"
    }

    set errors [lindex $results 0]
    set warnings [lindex $results 1]

    if {[llength $errors] > 0} {
        return "FAIL: errors unexpectedly encountered: $errors"
    }

    if {[llength $warnings] > 0} {
        if {[lsearch -regexp $warnings {missing.+recommended}] == -1} {
            return "FAIL: missing expected warning about recommended fields"
        }

        if {[llength [lsearch -inline \
                              -regexp \
                              -all $warnings {missing.+recommended}]] != 2} {
            return "FAIL: less warnings than expected: $warnings"
        }
    } else {
        return "FAIL: unexpectedly encountered no warnings"
    }

    return "lint_checksum_basic passed"
} -result "lint_checksum_basic passed"

test test_lint_checksum_basic_w_filename {
    Verify linting the most basic checksum that is still valid (with filename)
} -body {
    set checksum "checksum doop.tgz size 1"

    set results [portlint::lint_checksum $checksum]

    if {[llength $results] == 0} {
        return "FAIL: invalid results returned: empty list"
    }

    set errors [lindex $results 0]
    set warnings [lindex $results 1]

    if {[llength $errors] > 0} {
        return "FAIL: errors unexpectedly encountered: $errors"
    }

    if {[llength $warnings] > 0} {
        if {[lsearch -regexp $warnings \
                                {doop\.tgz.+missing.+recommended}] == -1} {
            return "FAIL: missing expected warning about recommended fields"
        }

        if {[llength [lsearch -inline \
                              -regexp \
                              -all $warnings \
                              {doop\.tgz.+missing.+recommended}]] != 2} {
            return "FAIL: less warnings than expected: $warnings"
        }
    } else {
        return "FAIL: unexpectedly encountered no warnings"
    }

    return "lint_checksum_basic filename passed"
} -result "lint_checksum_basic filename passed"

test test_lint_checksum_normal {
    Verify linting the standard checksum returns no errors or warnings
} -body {
    set checksum \
        "checksum sha256  3b413cdc29d91c91102628eb9b48e65a6827afe5441a46ad4d602e254945b24d
                  rmd160  b7240735e8ca7ad7a263a4bb69935ad68b34a878
                  size    11242"

    set results [portlint::lint_checksum $checksum]

    if {[llength $results] == 0} {
        return "FAIL: invalid results returned: empty list"
    }

    set errors [lindex $results 0]
    set warnings [lindex $results 1]

    if {[llength $errors] != 0} {
        return "FAIL: unexpectedly encountered errors: $errors"
    }

    if {[llength $warnings] != 0} {
        return "FAIL: unexpectedly encountered warnings: $warnings"
    }

    return "lint_checksum_normal passed"
} -result "lint_checksum_normal passed"

test test_lint_checksum_normal_w_filename {
    Verify linting the standard checksum returns no errors or warnings (with
    filename)
} -body {
    set checksum \
        "checksum somefile.tar
                  sha256  3b413cdc29d91c91102628eb9b48e65a6827afe5441a46ad4d602e254945b24d
                  rmd160  b7240735e8ca7ad7a263a4bb69935ad68b34a878
                  size    11242"

    set results [portlint::lint_checksum $checksum]

    if {[llength $results] == 0} {
        return "FAIL: invalid results returned: empty list"
    }

    set errors [lindex $results 0]
    set warnings [lindex $results 1]

    if {[llength $errors] != 0} {
        return "FAIL: unexpectedly encountered errors: $errors"
    }

    if {[llength $warnings] != 0} {
        return "FAIL: unexpectedly encountered warnings: $warnings"
    }

    return "lint_checksum_normal_w_filename passed"
} -result "lint_checksum_normal_w_filename passed"

test test_lint_checksum_bad_checksum_type {
    Verify that we catch invalid checksum types while linting checksums
} -body {
    set checksum \
        "checksum sha256  ea0d7ca87aab70c12817df5893f6bfe0492ce63f6e0e63c0b452e375344c7ef7
                  rmd160  f6a98b558f01e4c4fd078c106e6862436094fa3d
                  sha300  thischecksumtypedoesnotexist
                  size    11242"

    set results [portlint::lint_checksum $checksum]

    if {[llength $results] == 0} {
        return "FAIL: invalid results returned: empty list"
    }

    set errors [lindex $results 0]
    set warnings [lindex $results 1]

    if {[llength $errors] == 0} {
        return "FAIL: unexpectedly encountered no errors"
    }

    if {[lsearch -regexp $errors {invalid.+sha300}] == -1} {
        return "FAIL: no error present about the invalid checksum type: $errors"
    }

    return "lint_checksum_bad_checksum_type passed"
} -result "lint_checksum_bad_checksum_type passed"

test test_lint_checksum_bad_checksum_type_w_filename {
    Verify that we catch invalid checksum types while linting checksums (with
    filename)
} -body {
    set checksum \
        "checksum somefile.tar
                  sha256  ea0d7ca87aab70c12817df5893f6bfe0492ce63f6e0e63c0b452e375344c7ef7
                  rmd160  57353feec9a4bb9d5192705ad0403422bbd33007
                  sha300  thischecksumtypedoesnotexist
                  size    11242"

    set results [portlint::lint_checksum $checksum]

    if {[llength $results] == 0} {
        return "FAIL: invalid results returned: empty list"
    }

    set errors [lindex $results 0]
    set warnings [lindex $results 1]

    if {[llength $errors] == 0} {
        return "FAIL: unexpectedly encountered no errors"
    }

    if {[lsearch -regexp $errors {invalid.+field}] == -1} {
        return "FAIL: no error present about the invalid checksum type: $errors"
    }

    return "lint_checksum_bad_checksum_type_w_filename passed"
} -result "lint_checksum_bad_checksum_type_w_filename passed"

test test_lint_checksum_multi_basic {
    Verify basic checksums for multiple files
} -body {
    set checksum \
        "checksum file1.tar size 1
                  file2.tar size 1
                  file3.tar size 1"

    set results [portlint::lint_checksum $checksum]

    if {[llength $results] == 0} {
        return "FAIL: invalid results returned: empty list"
    }

    if {[lsearch -regexp $results {file1\.tar.+recommended}] == -1} {
        return "FAIL: no expected warnings for file1: $results"
    }

    if {[lsearch -regexp $results {file2\.tar.+recommended}] == -1} {
        return "FAIL: no expected warnings for file2: $results"
    }

    if {[lsearch -regexp $results {file3\.tar.+recommended}] == -1} {
        return "FAIL: no expected warnings for file3: $results"
    }

    return "lint_checksum_multi_basic passed"
} -result "lint_checksum_multi_basic passed"

test test_lint_checksum_multi_normal_w_filename {
    Verify normal checksums for multiple files
} -body {
    set checksum \
        "checksum file1.tar
                    sha256  3bb9d40e802e51f56f1364abc553758152131803c12d85ba6e14bad6813409d5
                    rmd160  880690684f35730351dac2cdfd928a7610f69cce
                    size    34554
                  file2.tar
                    sha256  2f686816f2a80e3lfn23jknf23jknp8d27ce4205a61ee422d56f8c5e8b4609e4
                    rmd160  5aee5d12fe536e2e288e9f1daafd84f1bc17c3e6
                    size    25644
                  file3.tar
                    sha256  250a86b79c231001c4ae71d2f66428092a4fbb2070971acafd471aa49739c9e4
                    rmd160  767d402a1a368f083c16a81ff31dde1870f451dc
                    size    11242"

    set results [portlint::lint_checksum $checksum]

    if {[llength $results] == 0} {
        return "FAIL: invalid results returned: empty list"
    }

    set errors [lindex $results 0]
    set warnings [lindex $results 1]

    if {[llength $errors] != 0} {
        return "FAIL: unexpectedly encountered errors: $errors"
    }

    if {[llength $warnings] != 0} {
        return "FAIL: unexpectedly encountered warnings: $warnings"
    }

    return "lint_checksum_multi_normal_w_filename passed"
} -result "lint_checksum_multi_normal_w_filename passed"

test test_lint_checksum_malformed_sha256 {
    Verify that we catch malformed SHA256 checksums
} -body {
    set checksum "checksum sha256 thisisnotcorrect"

    set results [portlint::lint_checksum $checksum]

    if {[llength $results] == 0} {
        return "FAIL: invalid results returned: empty list"
    }

    set errors [lindex $results 0]
    set warnings [lindex $results 1]

    if {[llength $errors] == 0} {
        return "FAIL: unexpectedly encountered errors: $errors"
    }

    if {[lsearch -regexp $errors {checksum.+sha256.+invalid}] == -1} {
        return "FAIL: missing error about invalid checksum: $errors"
    }

    return "lint_checksum_malformed_sha256 passed"
} -result "lint_checksum_malformed_sha256 passed"

test test_lint_checksum_malformed_rmd160 {
    Verify that we catch malformed RIPEMD160 checksums
} -body {
    set checksum "checksum rmd160 thisisnotcorrect"

    set results [portlint::lint_checksum $checksum]

    if {[llength $results] == 0} {
        return "FAIL: invalid results returned: empty list"
    }

    set errors [lindex $results 0]
    set warnings [lindex $results 1]

    if {[llength $errors] == 0} {
        return "FAIL: unexpectedly encountered errors: $errors"
    }

    if {[lsearch -regexp $errors {checksum.+rmd160.+invalid}] == -1} {
        return "FAIL: missing error about invalid checksum: $errors"
    }

    return "lint_checksum_malformed_rmd160 passed"
} -result "lint_checksum_malformed_rmd160 passed"

test test_lint_checksum_malformed_size {
    Verify that we catch malformed size checksum fields
} -body {
    set checksum "checksum size 1221A3"

    set results [portlint::lint_checksum $checksum]

    if {[llength $results] == 0} {
        return "FAIL: invalid results returned: empty list"
    }

    set errors [lindex $results 0]
    set warnings [lindex $results 1]

    if {[llength $errors] == 0} {
        return "FAIL: unexpectedly encountered errors: $errors"
    }

    if {[lsearch -regexp $errors {checksum.+size.+invalid}] == -1} {
        return "FAIL: missing error about invalid checksum: $errors"
    }

    return "lint_checksum_malformed_size passed"
} -result "lint_checksum_malformed_size passed"

test test_lint_checksum_multi_malformed {
    Verify that we catch malformed checksums after another checksum
} -body {
    set checksum "checksum  size   11213
                            sha256 thisisnotcorrect"

    set results [portlint::lint_checksum $checksum]

    if {[llength $results] == 0} {
        return "FAIL: invalid results returned: empty list"
    }

    set errors [lindex $results 0]
    set warnings [lindex $results 1]

    if {[llength $errors] == 0} {
        return "FAIL: unexpectedly encountered errors: $errors"
    }

    if {[lsearch -regexp $errors {checksum.+sha256.+invalid}] == -1} {
        return "FAIL: missing error about invalid checksum: $errors"
    }

    return "lint_checksum_multi_malformed passed"
} -result "lint_checksum_multi_malformed passed"

test test_lint_checksum_multi_malformed_w_filename_1 {
    Verify that we catch malformed checksums for multiple files (1)
} -body {
    set checksum "checksum  somefile.tar
                            size   11213
                            sha256 thisisnotcorrect"

    set results [portlint::lint_checksum $checksum]

    if {[llength $results] == 0} {
        return "FAIL: invalid results returned: empty list"
    }

    set errors [lindex $results 0]
    set warnings [lindex $results 1]

    if {[llength $errors] == 0} {
        return "FAIL: unexpectedly encountered no errors"
    }

    if {[llength $warnings] == 0} {
        return "FAIL: unexpectedly encountered no warnings"
    }

    if {[lsearch -regexp $errors {somefile.+checksum.+sha256.+invalid}] == -1} {
        return "FAIL: missing error about invalid checksum: $errors"
    }

    if {[lsearch -regexp $warnings {missing.+recommended.+rmd160}] == -1} {
        return "FAIL: missing expected warning about missing recommended type"
    }

    return "lint_checksum_multi_malformed_w_filename_1 passed"
} -result "lint_checksum_multi_malformed_w_filename_1 passed"

test test_lint_checksum_multi_malformed_w_filename_2 {
    Verify that we catch malformed checksums for multiple files (2)
} -body {
    set checksum \
        "checksum   somefile.tar
                        sha256 3bb9d40e802e51f56f1364abc553758152131803c12d85ba6e14bad6813409d5
                        size   11213
                    somefile2.tar
                        sha256 thisiscompletelymalformed
                        size   25433"

    set results [portlint::lint_checksum $checksum]

    if {[llength $results] == 0} {
        return "FAIL: invalid results returned: empty list"
    }

    set errors [lindex $results 0]
    set warnings [lindex $results 1]

    if {[llength $errors] == 0} {
        return "FAIL: unexpectedly encountered no errors"
    }

    if {[llength $warnings] == 0} {
        return "FAIL: unexpectedly encountered no warnings"
    }

    if {[lsearch -regexp $errors {somefile.+checksum.+sha256.+invalid}] == -1} {
        return "FAIL: missing error about invalid checksum: $errors"
    }

    if {[lsearch -regexp $warnings {somefile.+missing.+recommended.+rmd160}] == -1} {
        return "FAIL: missing warnings about missing recommended type"
    }

    return "lint_checksum_multi_malformed_w_filename_2 passed"
} -result "lint_checksum_multi_malformed_w_filename_2 passed"

test test_lint_checksum_multi_adjacent_invalid_w_filename {
    Verify that we catch adjacent invalid checksum fields within multiple files
} -body {
    set checksum \
        "checksum   somefile.tar
                        sha256 3bb9d40e802e51f56f1364abc553758152131803c12d85ba6e14bad6813409d5
                        size   11213
                    somefile2.tar
                        nope thisiscompletelyincorrect
                        size   25433"

    set results [portlint::lint_checksum $checksum]

    if {[llength $results] == 0} {
        return "FAIL: invalid results returned: empty list"
    }

    set errors [lindex $results 0]
    set warnings [lindex $results 1]

    if {[llength $errors] == 0} {
        return "FAIL: unexpectedly encountered errors: $errors"
    }

    if {[lsearch -regexp $errors {invalid.+field.+nope}] == -1} {
        return "FAIL: missing error about invalid checksum field: $errors"
    }

    if {[lsearch -regexp $warnings {somefile.+missing.+recommended.+rmd160}] == -1} {
        return "FAIL: missing warnings about missing recommended type: rmd160"
    }

    return "lint_checksum_multi_adjacent_invalid_w_filename passed"
} -result "lint_checksum_multi_adjacent_invalid_w_filename passed"

test test_lint_checksum_invalid_ending {
    Verify that we catch checksums that end with an invalid field
} -body {
    set checksum \
        "checksum rmd160 880690684f35730351dac2cdfd928a7610f69cce bunny"

    set results [portlint::lint_checksum $checksum]

    if {[llength $results] == 0} {
        return "FAIL: invalid results returned: empty list"
    }

    set errors [lindex $results 0]
    set warnings [lindex $results 1]

    if {[llength $errors] == 0} {
        return "FAIL: unexpectedly encountered no errors"
    }

    if {[llength $warnings] == 0} {
        return "FAIL: unexpectedly encountered no warnings"
    }

    if {[lsearch -regexp $errors {invalid.+field.+bunny}] == -1} {
        return "FAIL: missing error about invalid checksum field: $errors"
    }

    if {[lsearch -regexp $warnings {missing.+recommended}] == -1} {
        return "FAIL: no warnings about missing recommended types: $warnings"
    }

    return "lint_checksum_invalid_ending passed"
} -result "lint_checksum_invalid_ending passed"

test test_lint_checksum_invalid_ending_w_filename {
    Verify that we catch checksums that end with an invalid field
} -body {
    set checksum \
        "checksum file1.tar
                    rmd160 880690684f35730351dac2cdfd928a7610f69cce
                  bunny"

    set results [portlint::lint_checksum $checksum]

    if {[llength $results] == 0} {
        return "FAIL: invalid results returned: empty list"
    }

    set errors [lindex $results 0]
    set warnings [lindex $results 1]

    if {[llength $errors] == 0} {
        return "FAIL: unexpectedly encountered no errors"
    }

    if {[llength $warnings] == 0} {
        return "FAIL: unexpectedly encountered no warnings"
    }

    if {[lsearch -regexp $errors {invalid.+bunny}] == -1} {
        return "FAIL: missing error about invalid field: $errors"
    }

    if {[lsearch -regexp $warnings {file1.+missing.+recommended}] == -1} {
        return "FAIL: no warnings about missing recommended types: $warnings"
    }

    return "lint_checksum_invalid_ending_w_filename passed"
} -result "lint_checksum_invalid_ending_w_filename passed"

cleanupTests
