From c7cfeb8adb91e8a00b0ccfd9fbb925fdcf209872 Mon Sep 17 00:00:00 2001
From: Thomas Munro <thomas.munro@gmail.com>
Date: Tue, 21 Apr 2020 20:48:20 +1200
Subject: [PATCH v6 6/6] Add TAP test for snapshot too old time map
 maintenance.

---
 .../t/002_xid_map_maintenance.pl              | 63 +++++++++++++++++++
 1 file changed, 63 insertions(+)
 create mode 100644 src/test/modules/snapshot_too_old/t/002_xid_map_maintenance.pl

diff --git a/src/test/modules/snapshot_too_old/t/002_xid_map_maintenance.pl b/src/test/modules/snapshot_too_old/t/002_xid_map_maintenance.pl
new file mode 100644
index 0000000000..eddd0ce5ae
--- /dev/null
+++ b/src/test/modules/snapshot_too_old/t/002_xid_map_maintenance.pl
@@ -0,0 +1,63 @@
+# Test xid various time/xid map maintenance edge cases
+# that were historically buggy.
+
+use strict;
+use warnings;
+use PostgresNode;
+use TestLib;
+use Test::More tests => 8;
+
+my $node = get_new_node('master');
+$node->init;
+$node->append_conf("postgresql.conf", "timezone = UTC");
+$node->append_conf("postgresql.conf", "old_snapshot_threshold=10");
+$node->append_conf("postgresql.conf", "autovacuum = off");
+$node->start;
+$node->psql('postgres', 'create extension test_sto');
+$node->psql('postgres', 'create extension old_snapshot');
+
+sub set_time
+{
+	my $time = shift;
+	$node->psql('postgres', "select test_sto_clobber_snapshot_timestamp('$time')");
+}
+
+sub summarize_mapping
+{
+	my $out;
+	$node->psql('postgres',
+				"select count(*),
+						to_char(min(end_timestamp), 'HH24:MI:SS'),
+						to_char(max(end_timestamp), 'HH24:MI:SS')
+						from pg_old_snapshot_time_mapping()",
+				stdout => \$out);
+	return $out;
+}
+
+# fill the map up to maximum capacity
+set_time('3000-01-01 00:00:00Z');
+set_time('3000-01-01 00:19:00Z');
+is(summarize_mapping(), "20|00:00:00|00:19:00");
+
+# make a jump larger than capacity; the mapping is blown away,
+# and our new minute is now the only one
+set_time('3000-01-01 02:00:00Z');
+is(summarize_mapping(), "1|02:00:00|02:00:00");
+
+# test adding minutes while the map is not full
+set_time('3000-01-01 02:01:00Z');
+is(summarize_mapping(), "2|02:00:00|02:01:00");
+set_time('3000-01-01 02:05:00Z');
+is(summarize_mapping(), "6|02:00:00|02:05:00");
+set_time('3000-01-01 02:19:00Z');
+is(summarize_mapping(), "20|02:00:00|02:19:00");
+
+# test adding minutes while the map is full
+set_time('3000-01-01 02:20:00Z');
+is(summarize_mapping(), "20|02:01:00|02:20:00");
+set_time('3000-01-01 02:22:00Z');
+is(summarize_mapping(), "20|02:03:00|02:22:00");
+set_time('3000-01-01 02:22:01Z'); # one second past
+is(summarize_mapping(), "20|02:04:00|02:23:00");
+
+$node->stop;
-- 
2.20.1

