diff --git a/src/test/regress/expected/create_role.out b/src/test/regress/expected/create_role.out
new file mode 100644
index 0000000000..57010bbb58
--- /dev/null
+++ b/src/test/regress/expected/create_role.out
@@ -0,0 +1,145 @@
+-- ok, superuser can create users with any set of privileges
+CREATE ROLE regress_role_super SUPERUSER;
+CREATE ROLE regress_role_1 CREATEDB CREATEROLE REPLICATION BYPASSRLS;
+-- fail, only superusers can create users with these privileges
+SET SESSION AUTHORIZATION regress_role_1;
+CREATE ROLE regress_role_2 SUPERUSER;
+ERROR:  must be superuser to create superusers
+CREATE ROLE regress_role_3 REPLICATION BYPASSRLS;
+ERROR:  must be superuser to create replication users
+CREATE ROLE regress_role_4 REPLICATION;
+ERROR:  must be superuser to create replication users
+CREATE ROLE regress_role_5 BYPASSRLS;
+ERROR:  must be superuser to create bypassrls users
+-- ok, having CREATEROLE is enough to create users with these privileges
+CREATE ROLE regress_role_6 CREATEDB;
+CREATE ROLE regress_role_7 CREATEROLE;
+CREATE ROLE regress_role_8 LOGIN;
+CREATE ROLE regress_role_9 INHERIT;
+CREATE ROLE regress_role_10 CONNECTION LIMIT 5;
+CREATE ROLE regress_role_11 ENCRYPTED PASSWORD 'foo';
+CREATE ROLE regress_role_12 PASSWORD NULL;
+-- ok, backwards compatible noise words should be ignored
+CREATE ROLE regress_role_13 SYSID 12345;
+NOTICE:  SYSID can no longer be specified
+-- fail, cannot grant membership in superuser role
+CREATE ROLE regress_role_14 IN ROLE regress_role_super;
+ERROR:  must be superuser to alter superusers
+-- fail, database owner cannot have members
+CREATE ROLE regress_role_15 IN ROLE pg_database_owner;
+ERROR:  role "pg_database_owner" cannot have explicit members
+-- ok, can grant other users into a role
+CREATE ROLE regress_role_16 ROLE
+	regress_role_super, regress_role_6, regress_role_7, regress_role_8,
+	regress_role_9, regress_role_10, regress_role_11, regress_role_12;
+-- fail, cannot grant a role into itself
+CREATE ROLE regress_role_17 ROLE regress_role_17;
+ERROR:  role "regress_role_17" is a member of role "regress_role_17"
+-- ok, can grant other users into a role with admin option
+CREATE ROLE regress_role_18 ADMIN
+	regress_role_super, regress_role_6, regress_role_7, regress_role_8,
+	regress_role_9, regress_role_10, regress_role_11, regress_role_12;
+-- fail, cannot grant a role into itself with admin option
+CREATE ROLE regress_role_19 ADMIN regress_role_19;
+ERROR:  role "regress_role_19" is a member of role "regress_role_19"
+-- fail, regress_role_7 does not have CREATEDB privilege
+SET SESSION AUTHORIZATION regress_role_7;
+CREATE DATABASE regress_db_7;
+ERROR:  permission denied to create database
+-- ok, regress_role_7 can create new roles
+CREATE ROLE regress_role_20;
+-- ok, roles with CREATEROLE can create new roles with it
+CREATE ROLE regress_role_21 CREATEROLE;
+-- ok, roles with CREATEROLE can create new roles with privilege they lack
+CREATE ROLE regress_role_22 CREATEDB CREATEROLE LOGIN INHERIT CONNECTION LIMIT 5;
+-- ok, regress_role_22 can create objects within the database
+SET SESSION AUTHORIZATION regress_role_22;
+CREATE TABLE regress_tbl_22 (i integer);
+CREATE INDEX regress_idx_22 ON regress_tbl_22(i);
+CREATE VIEW regress_view_22 AS SELECT * FROM pg_catalog.pg_class;
+REVOKE ALL PRIVILEGES ON regress_tbl_22 FROM PUBLIC;
+-- fail, these objects belonging to regress_role_22
+SET SESSION AUTHORIZATION regress_role_7;
+DROP INDEX regress_idx_22;
+ERROR:  must be owner of index regress_idx_22
+ALTER TABLE regress_tbl_22 ADD COLUMN t text;
+ERROR:  must be owner of table regress_tbl_22
+DROP TABLE regress_tbl_22;
+ERROR:  must be owner of table regress_tbl_22
+ALTER VIEW regress_view_22 OWNER TO regress_role_1;
+ERROR:  must be owner of view regress_view_22
+DROP VIEW regress_view_22;
+ERROR:  must be owner of view regress_view_22
+-- fail, cannot take ownership of these objects from regress_role_22
+REASSIGN OWNED BY regress_role_22 TO regress_role_7;
+ERROR:  permission denied to reassign objects
+-- ok, having CREATEROLE is enough to create roles in privileged roles
+CREATE ROLE regress_role_23 IN ROLE pg_read_all_data;
+CREATE ROLE regress_role_24 IN ROLE pg_write_all_data;
+CREATE ROLE regress_role_25 IN ROLE pg_monitor;
+CREATE ROLE regress_role_26 IN ROLE pg_read_all_settings;
+CREATE ROLE regress_role_27 IN ROLE pg_read_all_stats;
+CREATE ROLE regress_role_28 IN ROLE pg_stat_scan_tables;
+CREATE ROLE regress_role_29 IN ROLE pg_read_server_files;
+CREATE ROLE regress_role_30 IN ROLE pg_write_server_files;
+CREATE ROLE regress_role_31 IN ROLE pg_execute_server_program;
+CREATE ROLE regress_role_32 IN ROLE pg_signal_backend;
+-- fail, creation of these roles failed above so they do not now exist
+SET SESSION AUTHORIZATION regress_role_1;
+DROP ROLE regress_role_2;
+ERROR:  role "regress_role_2" does not exist
+DROP ROLE regress_role_3;
+ERROR:  role "regress_role_3" does not exist
+DROP ROLE regress_role_4;
+ERROR:  role "regress_role_4" does not exist
+DROP ROLE regress_role_5;
+ERROR:  role "regress_role_5" does not exist
+DROP ROLE regress_role_14;
+ERROR:  role "regress_role_14" does not exist
+DROP ROLE regress_role_15;
+ERROR:  role "regress_role_15" does not exist
+DROP ROLE regress_role_17;
+ERROR:  role "regress_role_17" does not exist
+DROP ROLE regress_role_19;
+ERROR:  role "regress_role_19" does not exist
+DROP ROLE regress_role_20;
+-- ok, should be able to drop non-superuser roles we created
+DROP ROLE regress_role_6;
+DROP ROLE regress_role_7;
+DROP ROLE regress_role_8;
+DROP ROLE regress_role_9;
+DROP ROLE regress_role_10;
+DROP ROLE regress_role_11;
+DROP ROLE regress_role_12;
+DROP ROLE regress_role_13;
+DROP ROLE regress_role_16;
+DROP ROLE regress_role_18;
+DROP ROLE regress_role_21;
+DROP ROLE regress_role_23;
+DROP ROLE regress_role_24;
+DROP ROLE regress_role_25;
+DROP ROLE regress_role_26;
+DROP ROLE regress_role_27;
+DROP ROLE regress_role_28;
+DROP ROLE regress_role_29;
+DROP ROLE regress_role_30;
+DROP ROLE regress_role_31;
+DROP ROLE regress_role_32;
+-- fail, role still owns database objects
+DROP ROLE regress_role_22;
+ERROR:  role "regress_role_22" cannot be dropped because some objects depend on it
+DETAIL:  owner of table regress_tbl_22
+owner of view regress_view_22
+-- fail, cannot drop ourself nor superusers
+DROP ROLE regress_role_super;
+ERROR:  must be superuser to drop superusers
+DROP ROLE regress_role_1;
+ERROR:  current user cannot be dropped
+-- ok
+RESET SESSION AUTHORIZATION;
+DROP INDEX regress_idx_22;
+DROP TABLE regress_tbl_22;
+DROP VIEW regress_view_22;
+DROP ROLE regress_role_22;
+DROP ROLE regress_role_1;
+DROP ROLE regress_role_super;
diff --git a/src/test/regress/parallel_schedule b/src/test/regress/parallel_schedule
index 017e962fed..18dfdf5be8 100644
--- a/src/test/regress/parallel_schedule
+++ b/src/test/regress/parallel_schedule
@@ -86,7 +86,7 @@ test: brin_bloom brin_multi
 # ----------
 # Another group of parallel tests
 # ----------
-test: create_table_like alter_generic alter_operator misc async dbsize misc_functions sysviews tsrf tid tidscan tidrangescan collate.icu.utf8 incremental_sort
+test: create_table_like alter_generic alter_operator misc async dbsize misc_functions sysviews tsrf tid tidscan tidrangescan collate.icu.utf8 incremental_sort create_role
 
 # rules cannot run concurrently with any test that creates
 # a view or rule in the public schema
diff --git a/src/test/regress/sql/create_role.sql b/src/test/regress/sql/create_role.sql
new file mode 100644
index 0000000000..e00893de4e
--- /dev/null
+++ b/src/test/regress/sql/create_role.sql
@@ -0,0 +1,138 @@
+-- ok, superuser can create users with any set of privileges
+CREATE ROLE regress_role_super SUPERUSER;
+CREATE ROLE regress_role_1 CREATEDB CREATEROLE REPLICATION BYPASSRLS;
+
+-- fail, only superusers can create users with these privileges
+SET SESSION AUTHORIZATION regress_role_1;
+CREATE ROLE regress_role_2 SUPERUSER;
+CREATE ROLE regress_role_3 REPLICATION BYPASSRLS;
+CREATE ROLE regress_role_4 REPLICATION;
+CREATE ROLE regress_role_5 BYPASSRLS;
+
+-- ok, having CREATEROLE is enough to create users with these privileges
+CREATE ROLE regress_role_6 CREATEDB;
+CREATE ROLE regress_role_7 CREATEROLE;
+CREATE ROLE regress_role_8 LOGIN;
+CREATE ROLE regress_role_9 INHERIT;
+CREATE ROLE regress_role_10 CONNECTION LIMIT 5;
+CREATE ROLE regress_role_11 ENCRYPTED PASSWORD 'foo';
+CREATE ROLE regress_role_12 PASSWORD NULL;
+
+-- ok, backwards compatible noise words should be ignored
+CREATE ROLE regress_role_13 SYSID 12345;
+
+-- fail, cannot grant membership in superuser role
+CREATE ROLE regress_role_14 IN ROLE regress_role_super;
+
+-- fail, database owner cannot have members
+CREATE ROLE regress_role_15 IN ROLE pg_database_owner;
+
+-- ok, can grant other users into a role
+CREATE ROLE regress_role_16 ROLE
+	regress_role_super, regress_role_6, regress_role_7, regress_role_8,
+	regress_role_9, regress_role_10, regress_role_11, regress_role_12;
+
+-- fail, cannot grant a role into itself
+CREATE ROLE regress_role_17 ROLE regress_role_17;
+
+-- ok, can grant other users into a role with admin option
+CREATE ROLE regress_role_18 ADMIN
+	regress_role_super, regress_role_6, regress_role_7, regress_role_8,
+	regress_role_9, regress_role_10, regress_role_11, regress_role_12;
+
+-- fail, cannot grant a role into itself with admin option
+CREATE ROLE regress_role_19 ADMIN regress_role_19;
+
+-- fail, regress_role_7 does not have CREATEDB privilege
+SET SESSION AUTHORIZATION regress_role_7;
+CREATE DATABASE regress_db_7;
+
+-- ok, regress_role_7 can create new roles
+CREATE ROLE regress_role_20;
+
+-- ok, roles with CREATEROLE can create new roles with it
+CREATE ROLE regress_role_21 CREATEROLE;
+
+-- ok, roles with CREATEROLE can create new roles with privilege they lack
+CREATE ROLE regress_role_22 CREATEDB CREATEROLE LOGIN INHERIT CONNECTION LIMIT 5;
+
+-- ok, regress_role_22 can create objects within the database
+SET SESSION AUTHORIZATION regress_role_22;
+CREATE TABLE regress_tbl_22 (i integer);
+CREATE INDEX regress_idx_22 ON regress_tbl_22(i);
+CREATE VIEW regress_view_22 AS SELECT * FROM pg_catalog.pg_class;
+REVOKE ALL PRIVILEGES ON regress_tbl_22 FROM PUBLIC;
+
+-- fail, these objects belonging to regress_role_22
+SET SESSION AUTHORIZATION regress_role_7;
+DROP INDEX regress_idx_22;
+ALTER TABLE regress_tbl_22 ADD COLUMN t text;
+DROP TABLE regress_tbl_22;
+ALTER VIEW regress_view_22 OWNER TO regress_role_1;
+DROP VIEW regress_view_22;
+
+-- fail, cannot take ownership of these objects from regress_role_22
+REASSIGN OWNED BY regress_role_22 TO regress_role_7;
+
+-- ok, having CREATEROLE is enough to create roles in privileged roles
+CREATE ROLE regress_role_23 IN ROLE pg_read_all_data;
+CREATE ROLE regress_role_24 IN ROLE pg_write_all_data;
+CREATE ROLE regress_role_25 IN ROLE pg_monitor;
+CREATE ROLE regress_role_26 IN ROLE pg_read_all_settings;
+CREATE ROLE regress_role_27 IN ROLE pg_read_all_stats;
+CREATE ROLE regress_role_28 IN ROLE pg_stat_scan_tables;
+CREATE ROLE regress_role_29 IN ROLE pg_read_server_files;
+CREATE ROLE regress_role_30 IN ROLE pg_write_server_files;
+CREATE ROLE regress_role_31 IN ROLE pg_execute_server_program;
+CREATE ROLE regress_role_32 IN ROLE pg_signal_backend;
+
+-- fail, creation of these roles failed above so they do not now exist
+SET SESSION AUTHORIZATION regress_role_1;
+DROP ROLE regress_role_2;
+DROP ROLE regress_role_3;
+DROP ROLE regress_role_4;
+DROP ROLE regress_role_5;
+DROP ROLE regress_role_14;
+DROP ROLE regress_role_15;
+DROP ROLE regress_role_17;
+DROP ROLE regress_role_19;
+DROP ROLE regress_role_20;
+
+-- ok, should be able to drop non-superuser roles we created
+DROP ROLE regress_role_6;
+DROP ROLE regress_role_7;
+DROP ROLE regress_role_8;
+DROP ROLE regress_role_9;
+DROP ROLE regress_role_10;
+DROP ROLE regress_role_11;
+DROP ROLE regress_role_12;
+DROP ROLE regress_role_13;
+DROP ROLE regress_role_16;
+DROP ROLE regress_role_18;
+DROP ROLE regress_role_21;
+DROP ROLE regress_role_23;
+DROP ROLE regress_role_24;
+DROP ROLE regress_role_25;
+DROP ROLE regress_role_26;
+DROP ROLE regress_role_27;
+DROP ROLE regress_role_28;
+DROP ROLE regress_role_29;
+DROP ROLE regress_role_30;
+DROP ROLE regress_role_31;
+DROP ROLE regress_role_32;
+
+-- fail, role still owns database objects
+DROP ROLE regress_role_22;
+
+-- fail, cannot drop ourself nor superusers
+DROP ROLE regress_role_super;
+DROP ROLE regress_role_1;
+
+-- ok
+RESET SESSION AUTHORIZATION;
+DROP INDEX regress_idx_22;
+DROP TABLE regress_tbl_22;
+DROP VIEW regress_view_22;
+DROP ROLE regress_role_22;
+DROP ROLE regress_role_1;
+DROP ROLE regress_role_super;
