require "vnd.dovecot.testsuite";
require "variables";
require "foreverypart";
require "mime";

/*
 * Basic functionality
 */

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 :mime :anychild :contains ["Subject", "Comments"] "Frobnitzm" {
		test_fail "failed to match header (1)";
	}

	if not header :mime :anychild :contains ["Subject", "Comments"] "nonsense" {
		test_fail "failed to match header(2)";
	}

	if not header :mime :anychild :matches "Keywords" "*, strange, *" {
		test_fail "failed to match header (3)";
	}

	if not header :mime :anychild :is "Comments" "This is nonsense." {
		test_fail "failed to match header (4)";
	}

	/* Must not match */
	if header :mime :anychild ["subject", "comments", "keywords"] "idiotic" {
		test_fail "matched nonsense";
	}

	/* Match first key */
	if not header :mime :anychild :contains ["keywords"] ["strange", "snot", "vreemd"] {
		test_fail "failed to match first key";
	}

	/* Match second key */
	if not header :mime :anychild :contains ["keywords"] ["raar", "strange", "vreemd"] {
		test_fail "failed to match second key";
	}

	/* Match last key */
	if not header :mime :anychild :contains ["keywords"] ["raar", "snot", "strange"] {
		test_fail "failed to match last key";
	}

	/* First header */
	if not header :mime :anychild :contains ["keywords", "subject"]
		["raar", "strange", "vreemd"] {
		test_fail "failed to match first header";
	}

	/* Second header */
	if not header :mime :anychild :contains ["subject", "keywords"]
		["raar", "strange", "vreemd"] {
		test_fail "failed to match second header";
	}
}

/*
 * Basic functionality - foreverypart
 */

test "Basic functionality - foreverypart" {
	foreverypart {
		/* Must match */
		if not header :mime :anychild :contains ["Subject", "Comments"] "Frobnitzm" {
			test_fail "failed to match header (1)";
		}

		if not header :mime :anychild :contains ["Subject", "Comments"] "nonsense" {
			test_fail "failed to match header(2)";
		}

		if not header :mime :anychild :matches "Keywords" "*, strange, *" {
			test_fail "failed to match header (3)";
		}

		if not header :mime :anychild :is "Comments" "This is nonsense." {
			test_fail "failed to match header (4)";
		}

		/* Must not match */
		if header :mime :anychild ["subject", "comments", "keywords"] "idiotic" {
			test_fail "matched nonsense";
		}

		/* Match first key */
		if not header :mime :anychild :contains ["keywords"] ["strange", "snot", "vreemd"] {
			test_fail "failed to match first key";
		}

		/* Match second key */
		if not header :mime :anychild :contains ["keywords"] ["raar", "strange", "vreemd"] {
			test_fail "failed to match second key";
		}

		/* Match last key */
		if not header :mime :anychild :contains ["keywords"] ["raar", "snot", "strange"] {
			test_fail "failed to match last key";
		}

		/* First header */
		if not header :mime :anychild :contains ["keywords", "subject"]
			["raar", "strange", "vreemd"] {
			test_fail "failed to match first header";
		}

		/* Second header */
		if not header :mime :anychild :contains ["subject", "keywords"]
			["raar", "strange", "vreemd"] {
			test_fail "failed to match second header";
		}
	}
}

/*
 * Matching empty key
 */

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 :mime :anychild :is "X-Caffeine" "" {
		test_fail ":is-matched non-empty header with empty string";
	}

	if not header :mime :anychild :contains "X-Caffeine" "" {
		test_fail "failed to match existing header with empty string";
	}

	if not header :mime :anychild :is "comments" "" {
		test_fail "failed to match empty header :mime :anychild with empty string";
	}

	if header :mime :anychild :contains "X-Nonsense" "" {
		test_fail ":contains-matched non-existent header with empty string";
	}
}

/*
 * Matching empty key - foreverypart
 */

test "Matching empty key - foreverypart" {
	foreverypart {
		if header :mime :anychild :is "X-Caffeine" "" {
			test_fail ":is-matched non-empty header with empty string";
		}

		if not header :mime :anychild :contains "X-Caffeine" "" {
			test_fail "failed to match existing header with empty string";
		}

		if not header :mime :anychild :is "comments" "" {
			test_fail "failed to match empty header :mime :anychild with empty string";
		}

		if header :mime :anychild :contains "X-Nonsense" "" {
			test_fail ":contains-matched non-existent header with empty string";
		}
	}
}

/*
 * Ignoring whitespace
 */

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 :mime :anychild :is "x-a" "Text" {
		if header :mime :anychild :matches "x-a" "*" {
			set "header" "${1}"; 
		}
		test_fail "header :mime :anychild test does not strip leading whitespace (header=`${header}`)";
	}

	if not header :mime :anychild :is "x-b" "Text" {
		if header :mime :anychild :matches "x-b" "*" {
			set "header" "${1}"; 
		}
		test_fail "header :mime :anychild test does not strip trailing whitespace (header=`${header}`)";
	}

	if not header :mime :anychild :is "subject" "Help" {
		if header :mime :anychild :matches "subject" "*" {
			set "header" "${1}"; 
		}
		test_fail "header :mime :anychild test does not strip both leading and trailing whitespace (header=`${header}`)";
	}
}

/*
 * Ignoring whitespace - foreverypart
 */

test "Ignoring whitespace - foreverypart" {
	foreverypart {
		if not header :mime :anychild :is "x-a" "Text" {
			if header :mime :anychild :matches "x-a" "*" {
				set "header" "${1}"; 
			}
			test_fail "header :mime :anychild test does not strip leading whitespace (header=`${header}`)";
		}

		if not header :mime :anychild :is "x-b" "Text" {
			if header :mime :anychild :matches "x-b" "*" {
				set "header" "${1}"; 
			}
			test_fail "header :mime :anychild test does not strip trailing whitespace (header=`${header}`)";
		}

		if not header :mime :anychild :is "subject" "Help" {
			if header :mime :anychild :matches "subject" "*" {
				set "header" "${1}"; 
			}
			test_fail "header :mime :anychild test does not strip both leading and trailing whitespace (header=`${header}`)";
		}
	}
}

/*
 * Absent or empty header
 */

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 :mime :anychild :matches "Cc" "?*" {
		test_fail "CC header is not absent or empty";
	}

	if header :mime :anychild :matches "Subject" "?*" {
		test_fail "Subject header is empty, but matched otherwise";
	}

	if header :mime :anychild :matches "Comment" "?*" {
		test_fail "Comment header is empty, but matched otherwise";
	}
}

/*
 * Absent or empty header - foreverypart
 */

test "Absent or empty header - foreverypart" {
	foreverypart {
		if not header :mime :anychild :matches "Cc" "?*" {
			test_fail "CC header is not absent or empty";
		}

		if header :mime :anychild :matches "Subject" "?*" {
			test_fail "Subject header is empty, but matched otherwise";
		}

		if header :mime :anychild :matches "Comment" "?*" {
			test_fail "Comment header is empty, but matched otherwise";
		}
	}
}


/*
 * Invalid header name
 */

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 :mime :anychild :contains "subject:" "" {
		test_fail "matched invalid header name";
	}

	if header :mime :anychild :contains "to!" "" {
		test_fail "matched invalid header name";
	}
}

/*
 * Invalid header name - foreverypart
 */

test "Invalid header name - foreverypart" {
	foreverypart {
		if header :mime :anychild :contains "subject:" "" {
			test_fail "matched invalid header name";
		}

		if header :mime :anychild :contains "to!" "" {
			test_fail "matched invalid header name";
		}
	}
}

/*
 * Folded headers
 */

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 headers" {
	if not header :mime :anychild :is "x-multiline"
		"This is a multi-line header body, which should be unfolded correctly." {
		test_fail "failed to properly unfold folded header.";
	}
}

/*
 * Folded headers - foreverypart
 */

test "Folded headers - foreverypart" {
	foreverypart {
		if not header :mime :anychild :is "x-multiline"
			"This is a multi-line header body, which should be unfolded correctly." {
			test_fail "failed to properly unfold folded header.";
		}
	}
}

/*
 * Multipart anychild
 */

test_set "message" text:
From: Hendrik <hendrik@example.com>
To: Harrie <harrie@example.com>
Date: Sat, 11 Oct 2010 00:31:44 +0200
Subject: Harrie is een prutser
Content-Type: multipart/mixed; boundary=AA
X-Test: AA

This is a multi-part message in MIME format.
--AA
Content-Type: multipart/mixed; boundary=BB
X-Test: BB

This is a multi-part message in MIME format.
--BB
Content-Type: text/plain; charset="us-ascii"
X-Test: CC

Hello

--BB
Content-Type: text/plain; charset="us-ascii"
X-Test: DD

Hello again

--BB--
This is the end of MIME multipart.

--AA
Content-Type: text/plain; charset="us-ascii"
X-Test: EE

And again

--AA--
This is the end of  MIME multipart.
.
;

test "Multipart anychild" {
	if not header :mime :anychild "X-Test" "AA" {
		test_fail "No AA";
	}
	if not header :mime :anychild "X-Test" "BB" {
		test_fail "No BB";
	}
	if not header :mime :anychild "X-Test" "CC" {
		test_fail "No CC";
	}
	if not header :mime :anychild "X-Test" "DD" {
		test_fail "No DD";
	}
	if not header :mime :anychild "X-Test" "EE" {
		test_fail "No EE";
	}
}


