require "vnd.dovecot.testsuite"; require "variables"; /* * ## RFC 5228, Section 5.7. Test header (page 29) ## */ /* * TEST: Basic functionality */ /* "The "header" test evaluates to true if the value of any of the named * headers, ignoring leading and trailing whitespace, matches any key. * The type of match is specified by the optional match argument, which * defaults to ":is" if not specified, as specified in section 2.6. * * Like address and envelope, this test returns true if any combination * of the header-names list and key-list arguments match and returns * false otherwise. * " */ test_set "message" text: From: stephan@example.com To: nico@nl.example.com, harry@de.example.com Subject: Frobnitzm Comments: This is nonsense. Keywords: nonsense, strange, testing X-Spam: Yes Test. . ; test "Basic functionality" { /* Must match */ if not header :contains ["Subject", "Comments"] "Frobnitzm" { test_fail "failed to match header (1)"; } if not header :contains ["Subject", "Comments"] "nonsense" { test_fail "failed to match header(2)"; } if not header :matches "Keywords" "*, strange, *" { test_fail "failed to match header (3)"; } if not header :is "Comments" "This is nonsense." { test_fail "failed to match header (4)"; } /* Must not match */ if header ["subject", "comments", "keywords"] "idiotic" { test_fail "matched nonsense"; } /* Match first key */ if not header :contains ["keywords"] ["strange", "snot", "vreemd"] { test_fail "failed to match first key"; } /* Match second key */ if not header :contains ["keywords"] ["raar", "strange", "vreemd"] { test_fail "failed to match second key"; } /* Match last key */ if not header :contains ["keywords"] ["raar", "snot", "strange"] { test_fail "failed to match last key"; } /* First header */ if not header :contains ["keywords", "subject"] ["raar", "strange", "vreemd"] { test_fail "failed to match first header"; } /* Second header */ if not header :contains ["subject", "keywords"] ["raar", "strange", "vreemd"] { test_fail "failed to match second header"; } } /* * TEST: Matching empty key */ /* "If a header listed in the header-names argument exists, it contains * the empty key (""). However, if the named header is not present, it * does not match any key, including the empty key. So if a message * contained the header * * X-Caffeine: C8H10N4O2 * * these tests on that header evaluate as follows: * * header :is ["X-Caffeine"] [""] => false * header :contains ["X-Caffeine"] [""] => true * " */ test_set "message" text: From: stephan@example.org To: nico@frop.example.com X-Caffeine: C8H10N4O2 Subject: I need coffee! Comments: Text . ; test "Matching empty key" { if header :is "X-Caffeine" "" { test_fail ":is-matched non-empty header with empty string"; } if not header :contains "X-Caffeine" "" { test_fail "failed to match existing header with empty string"; } if not header :is "comments" "" { test_fail "failed to match empty header with empty string"; } if header :contains "X-Nonsense" "" { test_fail ":contains-matched non-existent header with empty string"; } } /* * TEST: Ignoring whitespace */ /* "The "header" test evaluates to true if the value of any of the named * headers, ignoring leading and trailing whitespace, matches any key. * ... * " */ test_set "message" text: From: stephan@example.org To: nico@frop.example.com Subject: Help X-A: Text X-B: Text Text . ; test "Ignoring whitespace" { if not header :is "x-a" "Text" { if header :matches "x-a" "*" { set "header" "${1}"; } test_fail "header test does not strip leading whitespace (header=`${header}`)"; } if not header :is "x-b" "Text" { if header :matches "x-b" "*" { set "header" "${1}"; } test_fail "header test does not strip trailing whitespace (header=`${header}`)"; } if not header :is "subject" "Help" { if header :matches "subject" "*" { set "header" "${1}"; } test_fail "header test does not strip both leading and trailing whitespace (header=`${header}`)"; } } /* * TEST: Absent or empty header */ /* "Testing whether a given header is either absent or doesn't contain * any non-whitespace characters can be done using a negated "header" * test: * * not header :matches "Cc" "?*" * " */ test_set "message" text: From: stephan@example.org To: nico@frop.example.com CC: harry@nonsense.ex Subject: Comments: Text . ; test "Absent or empty header" { if not header :matches "Cc" "?*" { test_fail "CC header is not absent or empty"; } if header :matches "Subject" "?*" { test_fail "Subject header is empty, but matched otherwise"; } if header :matches "Comment" "?*" { test_fail "Comment header is empty, but matched otherwise"; } } /* * ## RFC 5228, Section 2.4.2.2. Headers (page 9) */ /* * TEST: Invalid header name */ /* "A header name never contains a colon. The "From" header refers to a * line beginning "From:" (or "From :", etc.). No header will match * the string "From:" due to the trailing colon. * * Similarly, no header will match a syntactically invalid header name. * An implementation MUST NOT cause an error for syntactically invalid * header names in tests. */ test_set "message" text: From: stephan@example.org To: nico@frop.example.com Subject: Valid message X-Multiline: This is a multi-line header body, which should be unfolded correctly. Text . ; test "Invalid header name" { if header :contains "subject:" "" { test_fail "matched invalid header name"; } if header :contains "to!" "" { test_fail "matched invalid header name"; } } /* * TEST: Folded headers */ /* "Header lines are unfolded as described in [RFC 2822] section 2.2.3. * ... * " */ test_set "message" text: From: stephan@example.org To: nico@frop.example.com Subject: Not enough space on a line! X-Multiline: This is a multi-line header body, which should be unfolded correctly. Text . ; test "Folded header" { if not header :is "x-multiline" "This is a multi-line header body, which should be unfolded correctly." { test_fail "failed to properly unfold folded header."; } }