From 75cd0f1349abb8d83f6afacf4e85bfbb744905ba Mon Sep 17 00:00:00 2001
From: Amit Kapila <akapila@postgresql.org>
Date: Wed, 20 Feb 2019 18:18:03 +0530
Subject: [PATCH] Add more tests for FSM.

In commit b0eaa4c51b, we left out a test that used a vacuum to remove dead
rows as the behavior of test was not predictable.  This test has been
rewritten to use fillfactor instead to control free space.  Since we no
longer need to remove dead rows as part of the test, put the fsm regression
test in a parallel group.

Author: John Naylor
Reviewed-by: Amit Kapila
Discussion: https://postgr.es/m/CAA4eK1L=qWp_bJ5aTc9+fy4Ewx2LPaLWY-RbR4a60g_rupCKnQ@mail.gmail.com
---
 src/test/regress/expected/fsm.out  | 36 +++++++++++++++++++++++++++++-------
 src/test/regress/parallel_schedule |  8 +-------
 src/test/regress/sql/fsm.sql       | 34 ++++++++++++++++++++++++++++------
 3 files changed, 58 insertions(+), 20 deletions(-)

diff --git a/src/test/regress/expected/fsm.out b/src/test/regress/expected/fsm.out
index b029931..f5f6242 100644
--- a/src/test/regress/expected/fsm.out
+++ b/src/test/regress/expected/fsm.out
@@ -1,15 +1,37 @@
 --
 -- Free Space Map test
 --
-CREATE TABLE fsm_check_size (num int, str text);
--- With one block, there should be no FSM
-INSERT INTO fsm_check_size VALUES(1, 'a');
+CREATE TABLE fsm_check_size (num1 int, num2 int, str text);
+-- Fill 3 blocks with one record each
+ALTER TABLE fsm_check_size SET (fillfactor=15);
+INSERT INTO fsm_check_size SELECT i, i, rpad('', 1024, 'a')
+FROM generate_series(1,3) i;
+-- There should be no FSM
 VACUUM fsm_check_size;
 SELECT pg_relation_size('fsm_check_size', 'main') AS heap_size,
 pg_relation_size('fsm_check_size', 'fsm') AS fsm_size;
  heap_size | fsm_size 
 -----------+----------
-      8192 |        0
+     24576 |        0
+(1 row)
+
+-- The following operations are for testing the functionality of the local
+-- in-memory map. In particular, we want to be able to insert into some
+-- other block than the one at the end of the heap, without using a FSM.
+-- Fill most of the last block
+ALTER TABLE fsm_check_size SET (fillfactor=100);
+INSERT INTO fsm_check_size SELECT i, i, rpad('', 1024, 'a')
+FROM generate_series(101,105) i;
+-- Make sure records can go into any block but the last one
+ALTER TABLE fsm_check_size SET (fillfactor=30);
+-- Insert large record and make sure it does not cause the relation to extend
+INSERT INTO fsm_check_size VALUES (111, 111, rpad('', 1024, 'a'));
+VACUUM fsm_check_size;
+SELECT pg_relation_size('fsm_check_size', 'main') AS heap_size,
+pg_relation_size('fsm_check_size', 'fsm') AS fsm_size;
+ heap_size | fsm_size 
+-----------+----------
+     24576 |        0
 (1 row)
 
 -- Extend table with enough blocks to exceed the FSM threshold
@@ -19,7 +41,7 @@ num int;
 BEGIN
 num = 11;
   LOOP
-    INSERT INTO fsm_check_size VALUES (num, 'b') RETURNING ctid INTO curtid;
+    INSERT INTO fsm_check_size VALUES (num, num, 'b') RETURNING ctid INTO curtid;
     EXIT WHEN curtid >= tid '(4, 0)';
     num = num + 1;
   END LOOP;
@@ -34,8 +56,8 @@ SELECT pg_relation_size('fsm_check_size', 'fsm') AS fsm_size;
 
 -- Add long random string to extend TOAST table to 1 block
 INSERT INTO fsm_check_size
-VALUES(0, (SELECT string_agg(md5(chr(i)), '')
-		   FROM generate_series(1,100) i));
+VALUES(0, 0, (SELECT string_agg(md5(chr(i)), '')
+			  FROM generate_series(1,100) i));
 VACUUM fsm_check_size;
 SELECT pg_relation_size(reltoastrelid, 'main') AS toast_size,
 pg_relation_size(reltoastrelid, 'fsm') AS toast_fsm_size
diff --git a/src/test/regress/parallel_schedule b/src/test/regress/parallel_schedule
index 4051a4a..a956775 100644
--- a/src/test/regress/parallel_schedule
+++ b/src/test/regress/parallel_schedule
@@ -23,7 +23,7 @@ test: numerology
 # ----------
 # The second group of parallel tests
 # ----------
-test: point lseg line box path polygon circle date time timetz timestamp timestamptz interval inet macaddr macaddr8 tstypes
+test: point lseg line box path polygon circle date time timetz timestamp timestamptz interval inet macaddr macaddr8 tstypes fsm
 
 # ----------
 # Another group of parallel tests
@@ -69,12 +69,6 @@ test: create_aggregate create_function_3 create_cast constraints triggers inheri
 test: sanity_check
 
 # ----------
-# fsm does a delete followed by vacuum, and running it in parallel can prevent
-# removal of rows.
-# ----------
-test: fsm
-
-# ----------
 # Believe it or not, select creates a table, subsequent
 # tests need.
 # ----------
diff --git a/src/test/regress/sql/fsm.sql b/src/test/regress/sql/fsm.sql
index 332c3e2..7ba22e5 100644
--- a/src/test/regress/sql/fsm.sql
+++ b/src/test/regress/sql/fsm.sql
@@ -2,10 +2,32 @@
 -- Free Space Map test
 --
 
-CREATE TABLE fsm_check_size (num int, str text);
+CREATE TABLE fsm_check_size (num1 int, num2 int, str text);
 
--- With one block, there should be no FSM
-INSERT INTO fsm_check_size VALUES(1, 'a');
+-- Fill 3 blocks with one record each
+ALTER TABLE fsm_check_size SET (fillfactor=15);
+INSERT INTO fsm_check_size SELECT i, i, rpad('', 1024, 'a')
+FROM generate_series(1,3) i;
+
+-- There should be no FSM
+VACUUM fsm_check_size;
+SELECT pg_relation_size('fsm_check_size', 'main') AS heap_size,
+pg_relation_size('fsm_check_size', 'fsm') AS fsm_size;
+
+-- The following operations are for testing the functionality of the local
+-- in-memory map. In particular, we want to be able to insert into some
+-- other block than the one at the end of the heap, without using a FSM.
+
+-- Fill most of the last block
+ALTER TABLE fsm_check_size SET (fillfactor=100);
+INSERT INTO fsm_check_size SELECT i, i, rpad('', 1024, 'a')
+FROM generate_series(101,105) i;
+
+-- Make sure records can go into any block but the last one
+ALTER TABLE fsm_check_size SET (fillfactor=30);
+
+-- Insert large record and make sure it does not cause the relation to extend
+INSERT INTO fsm_check_size VALUES (111, 111, rpad('', 1024, 'a'));
 
 VACUUM fsm_check_size;
 SELECT pg_relation_size('fsm_check_size', 'main') AS heap_size,
@@ -18,7 +40,7 @@ num int;
 BEGIN
 num = 11;
   LOOP
-    INSERT INTO fsm_check_size VALUES (num, 'b') RETURNING ctid INTO curtid;
+    INSERT INTO fsm_check_size VALUES (num, num, 'b') RETURNING ctid INTO curtid;
     EXIT WHEN curtid >= tid '(4, 0)';
     num = num + 1;
   END LOOP;
@@ -30,8 +52,8 @@ SELECT pg_relation_size('fsm_check_size', 'fsm') AS fsm_size;
 
 -- Add long random string to extend TOAST table to 1 block
 INSERT INTO fsm_check_size
-VALUES(0, (SELECT string_agg(md5(chr(i)), '')
-		   FROM generate_series(1,100) i));
+VALUES(0, 0, (SELECT string_agg(md5(chr(i)), '')
+			  FROM generate_series(1,100) i));
 
 VACUUM fsm_check_size;
 SELECT pg_relation_size(reltoastrelid, 'main') AS toast_size,
-- 
1.8.3.1

