diff --git a/tests/kms_rotation_crc.c b/tests/kms_rotation_crc.c
index 796b448..434f845 100644
--- a/tests/kms_rotation_crc.c
+++ b/tests/kms_rotation_crc.c
@@ -84,11 +84,25 @@ paint_squares(data_t *data, drmModeModeInfo *mode, igt_rotation_t rotation,
 	cairo_destroy(cr);
 }
 
-static void commit_crtc(data_t *data, igt_output_t *output, igt_plane_t *plane)
+static int display_commit_test_only(igt_display_t *display)
+{
+	int ret;
+
+	ret = igt_display_try_commit_atomic(display,
+					    DRM_MODE_ATOMIC_TEST_ONLY |
+					    DRM_MODE_ATOMIC_ALLOW_MODESET,
+					    NULL);
+
+	return ret;
+}
+
+static void commit_crtc(data_t *data, igt_output_t *output, igt_plane_t *plane,
+	bool test_only)
 {
 	igt_display_t *display = &data->display;
 	enum igt_commit_style commit = COMMIT_LEGACY;
 	igt_plane_t *primary;
+	int ret;
 
 	/*
 	 * With igt_display_commit2 and COMMIT_UNIVERSAL, we call just the
@@ -99,7 +113,13 @@ static void commit_crtc(data_t *data, igt_output_t *output, igt_plane_t *plane)
 
 	primary = igt_output_get_plane(output, IGT_PLANE_PRIMARY);
 	igt_plane_set_fb(primary, &data->fb_modeset);
-	igt_display_commit(display);
+
+	if (test_only) {
+		ret = display_commit_test_only(display);
+		igt_assert_eq(ret, 0);
+	} else {
+		igt_display_commit(display);
+	}
 
 	igt_plane_set_fb(plane, &data->fb);
 
@@ -111,12 +131,19 @@ static void commit_crtc(data_t *data, igt_output_t *output, igt_plane_t *plane)
 
 	if (data->display.is_atomic)
 		commit = COMMIT_ATOMIC;
+	else
+		igt_skip_on(test_only);
 
-	igt_display_commit2(display, commit);
+	if (test_only) {
+		ret = display_commit_test_only(display);
+		igt_assert_eq(ret, 0);
+	} else {
+		igt_display_commit2(display, commit);
+	}
 }
 
 static void prepare_crtc(data_t *data, igt_output_t *output, enum pipe pipe,
-			 igt_plane_t *plane)
+			 igt_plane_t *plane, bool test_only)
 {
 	drmModeModeInfo *mode;
 	int fb_id, fb_modeset_id;
@@ -181,8 +208,10 @@ static void prepare_crtc(data_t *data, igt_output_t *output, enum pipe pipe,
 
 	/* Step 1: create a reference CRC for a software-rotated fb */
 	paint_squares(data, mode, data->rotation, &data->fb, 1.0);
-	commit_crtc(data, output, plane);
-	igt_pipe_crc_collect_crc(data->pipe_crc, &data->ref_crc);
+	commit_crtc(data, output, plane, test_only);
+
+	if (!test_only)
+		igt_pipe_crc_collect_crc(data->pipe_crc, &data->ref_crc);
 
 	/*
 	 * Step 2: prepare the plane with an non-rotated fb let the hw
@@ -192,10 +221,12 @@ static void prepare_crtc(data_t *data, igt_output_t *output, enum pipe pipe,
 	igt_plane_set_fb(plane, &data->fb);
 }
 
-static void cleanup_crtc(data_t *data, igt_output_t *output, igt_plane_t *plane)
+static void cleanup_crtc(data_t *data, igt_output_t *output, igt_plane_t *plane,
+	bool test_only)
 {
 	igt_display_t *display = &data->display;
-
+	int ret;
+
 	igt_pipe_crc_free(data->pipe_crc);
 	data->pipe_crc = NULL;
 
@@ -215,7 +246,12 @@ static void cleanup_crtc(data_t *data, igt_output_t *output, igt_plane_t *plane)
 	igt_plane_set_fb(plane, NULL);
 	igt_output_set_pipe(output, PIPE_ANY);
 
-	igt_display_commit(display);
+	if (test_only) {
+		ret = display_commit_test_only(display);
+		igt_assert_eq(ret, 0);
+	} else {
+		igt_display_commit(display);
+	}
 }
 
 static void wait_for_pageflip(int fd)
@@ -235,7 +271,7 @@ static void wait_for_pageflip(int fd)
 	igt_assert(drmHandleEvent(fd, &evctx) == 0);
 }
 
-static void test_plane_rotation(data_t *data, enum igt_plane plane_type)
+static void test_plane_rotation(data_t *data, enum igt_plane plane_type, bool test_only)
 {
 	igt_display_t *display = &data->display;
 	igt_output_t *output;
@@ -254,6 +290,8 @@ static void test_plane_rotation(data_t *data, enum igt_plane plane_type)
 
 	if (data->display.is_atomic)
 		commit = COMMIT_ATOMIC;
+	else
+		igt_skip_on(test_only);
 
 	for_each_connected_output(display, output) {
 		for_each_pipe(display, pipe) {
@@ -264,17 +302,32 @@ static void test_plane_rotation(data_t *data, enum igt_plane plane_type)
 			plane = igt_output_get_plane(output, plane_type);
 			igt_require(igt_plane_supports_rotation(plane));
 
-			prepare_crtc(data, output, pipe, plane);
+			prepare_crtc(data, output, pipe, plane, test_only);
 
-			igt_display_commit2(display, commit);
+			if (test_only) {
+				ret = display_commit_test_only(display);
+				igt_assert_eq(ret, 0);
+			} else {
+				igt_display_commit2(display, commit);
+			}
 
 			/* collect unrotated CRC */
-			igt_pipe_crc_collect_crc(data->pipe_crc, &crc_unrotated);
+			if (!test_only)
+				igt_pipe_crc_collect_crc(data->pipe_crc, &crc_unrotated);
 
 			igt_plane_set_rotation(plane, data->rotation);
-			ret = igt_display_try_commit2(display, commit);
+
+			if (test_only) {
+				ret = display_commit_test_only(display);
+				igt_assert_eq(ret, 0);
+			} else {
+				ret = igt_display_try_commit2(display, commit);
+			}
+
 			if (data->override_fmt || data->override_tiling) {
 				igt_assert_eq(ret, -EINVAL);
+			} else if (test_only) {
+				igt_assert_eq(ret, 0);
 			} else {
 				igt_assert_eq(ret, 0);
 				igt_pipe_crc_collect_crc(data->pipe_crc,
@@ -283,22 +336,24 @@ static void test_plane_rotation(data_t *data, enum igt_plane plane_type)
 						     &crc_output);
 			}
 
-			flip_count = data->flip_stress;
-			while (flip_count--) {
-				ret = drmModePageFlip(data->gfx_fd,
-						      output->config.crtc->crtc_id,
-						      data->fb_flip.fb_id,
-						      DRM_MODE_PAGE_FLIP_EVENT,
-						      NULL);
-				igt_assert(ret == 0);
-				wait_for_pageflip(data->gfx_fd);
-				ret = drmModePageFlip(data->gfx_fd,
-						      output->config.crtc->crtc_id,
-						      data->fb.fb_id,
-						      DRM_MODE_PAGE_FLIP_EVENT,
-						      NULL);
-				igt_assert(ret == 0);
-				wait_for_pageflip(data->gfx_fd);
+			if (!test_only) {
+				flip_count = data->flip_stress;
+				while (flip_count--) {
+					ret = drmModePageFlip(data->gfx_fd,
+							      output->config.crtc->crtc_id,
+							      data->fb_flip.fb_id,
+							      DRM_MODE_PAGE_FLIP_EVENT,
+							      NULL);
+					igt_assert(ret == 0);
+					wait_for_pageflip(data->gfx_fd);
+					ret = drmModePageFlip(data->gfx_fd,
+							      output->config.crtc->crtc_id,
+							      data->fb.fb_id,
+							      DRM_MODE_PAGE_FLIP_EVENT,
+							      NULL);
+					igt_assert(ret == 0);
+					wait_for_pageflip(data->gfx_fd);
+				}
 			}
 
 			/*
@@ -307,20 +362,24 @@ static void test_plane_rotation(data_t *data, enum igt_plane plane_type)
 			 */
 			kmstest_restore_vt_mode();
 			kmstest_set_vt_graphics_mode();
+
+			commit_crtc(data, output, plane, test_only);
 
-			commit_crtc(data, output, plane);
-
-			igt_pipe_crc_collect_crc(data->pipe_crc, &crc_output);
-			igt_assert_crc_equal(&crc_unrotated, &crc_output);
+			if (!test_only) {
+				igt_pipe_crc_collect_crc(data->pipe_crc, &crc_output);
+				igt_assert_crc_equal(&crc_unrotated, &crc_output);
+			}
 
 			valid_tests++;
-			cleanup_crtc(data, output, plane);
+			cleanup_crtc(data, output, plane, test_only);
 		}
 	}
 	igt_require_f(valid_tests, "no valid crtc/connector combinations found\n");
 }
 
-static void test_plane_rotation_ytiled_obj(data_t *data, enum igt_plane plane_type)
+static void test_plane_rotation_ytiled_obj(data_t *data,
+					   enum igt_plane plane_type,
+					   bool test_only)
 {
 	igt_display_t *display = &data->display;
 	uint64_t tiling = LOCAL_I915_FORMAT_MOD_Y_TILED;
@@ -348,6 +407,8 @@ static void test_plane_rotation_ytiled_obj(data_t *data, enum igt_plane plane_ty
 
 	if (data->display.is_atomic)
 		commit = COMMIT_ATOMIC;
+	else
+		igt_skip_on(test_only);
 
 	mode = igt_output_get_mode(output);
 	w = mode->hdisplay;
@@ -379,14 +440,20 @@ static void test_plane_rotation_ytiled_obj(data_t *data, enum igt_plane plane_ty
 				 DRM_MODE_OBJECT_PLANE,
 				 plane->rotation_property,
 				 plane->rotation);
-	ret = igt_display_try_commit2(display, commit);
+
+	if (test_only)
+		ret = display_commit_test_only(display);
+	else
+		ret = igt_display_try_commit2(display, commit);
 
 	kmstest_restore_vt_mode();
 	igt_remove_fb(fd, &data->fb);
 	igt_assert(ret == 0);
 }
 
-static void test_plane_rotation_exhaust_fences(data_t *data, enum igt_plane plane_type)
+static void test_plane_rotation_exhaust_fences(data_t *data,
+					       enum igt_plane plane_type,
+					       bool test_only)
 {
 	igt_display_t *display = &data->display;
 	uint64_t tiling = LOCAL_I915_FORMAT_MOD_Y_TILED;
@@ -416,6 +483,8 @@ static void test_plane_rotation_exhaust_fences(data_t *data, enum igt_plane plan
 
 	if (data->display.is_atomic)
 		commit = COMMIT_ATOMIC;
+	else
+		igt_skip_on(test_only);
 
 	mode = igt_output_get_mode(output);
 	w = mode->hdisplay;
@@ -435,7 +504,13 @@ static void test_plane_rotation_exhaust_fences(data_t *data, enum igt_plane plan
 	igt_require(total_fbs_size < total_aperture_size * 0.9);
 
 	igt_plane_set_fb(plane, NULL);
-	igt_display_commit(display);
+
+	if (test_only) {
+		ret = display_commit_test_only(display);
+		igt_assert_eq(ret, 0);
+	} else {
+		igt_display_commit(display);
+	}
 
 	for (i = 0; i < MAX_FENCES + 1; i++) {
 		gem_handle = gem_create(fd, size);
@@ -460,10 +535,18 @@ static void test_plane_rotation_exhaust_fences(data_t *data, enum igt_plane plan
 		igt_plane_set_fb(plane, &data2[i].fb);
 		igt_plane_set_rotation(plane, IGT_ROTATION_0);
 
-		ret = igt_display_try_commit2(display, commit);
-		if (ret) {
-			igt_warn("failed to commit unrotated fb\n");
-			goto err_commit;
+		if (test_only) {
+			ret = display_commit_test_only(display);
+			if (ret) {
+				igt_warn("test only: failed to commit unrotated fb\n");
+				goto err_commit;
+			}
+		} else {
+			ret = igt_display_try_commit2(display, commit);
+			if (ret) {
+				igt_warn("failed to commit unrotated fb\n");
+				goto err_commit;
+			}
 		}
 
 		igt_plane_set_rotation(plane, IGT_ROTATION_90);
@@ -472,10 +555,19 @@ static void test_plane_rotation_exhaust_fences(data_t *data, enum igt_plane plan
 					 DRM_MODE_OBJECT_PLANE,
 					 plane->rotation_property,
 					 plane->rotation);
-		ret = igt_display_try_commit2(display, commit);
-		if (ret) {
-			igt_warn("failed to commit hardware rotated fb\n");
-			goto err_commit;
+
+		if (test_only) {
+			ret = display_commit_test_only(display);
+			if (ret) {
+				igt_warn("test only: failed to commit hardware rotated fb\n");
+				goto err_commit;
+			}
+		} else {
+			ret = igt_display_try_commit2(display, commit);
+			if (ret) {
+				igt_warn("failed to commit hardware rotated fb\n");
+				goto err_commit;
+			}
 		}
 	}
 
@@ -511,41 +603,73 @@ igt_main
 	}
 	igt_subtest_f("primary-rotation-180") {
 		data.rotation = IGT_ROTATION_180;
-		test_plane_rotation(&data, IGT_PLANE_PRIMARY);
+		test_plane_rotation(&data, IGT_PLANE_PRIMARY, false);
+	}
+	igt_subtest_f("primary-rotation-180-test-only") {
+		data.rotation = IGT_ROTATION_180;
+		test_plane_rotation(&data, IGT_PLANE_PRIMARY, true);
 	}
 
 	igt_subtest_f("sprite-rotation-180") {
 		data.rotation = IGT_ROTATION_180;
-		test_plane_rotation(&data, IGT_PLANE_2);
+		test_plane_rotation(&data, IGT_PLANE_2, false);
+	}
+	igt_subtest_f("sprite-rotation-180-test-only") {
+		data.rotation = IGT_ROTATION_180;
+		test_plane_rotation(&data, IGT_PLANE_2, true);
 	}
 
 	igt_subtest_f("cursor-rotation-180") {
 		data.rotation = IGT_ROTATION_180;
-		test_plane_rotation(&data, IGT_PLANE_CURSOR);
+		test_plane_rotation(&data, IGT_PLANE_CURSOR, false);
+	}
+	igt_subtest_f("cursor-rotation-180-test-only") {
+		data.rotation = IGT_ROTATION_180;
+		test_plane_rotation(&data, IGT_PLANE_CURSOR, true);
 	}
 
 	igt_subtest_f("primary-rotation-90") {
 		igt_require(gen >= 9);
 		data.rotation = IGT_ROTATION_90;
-		test_plane_rotation(&data, IGT_PLANE_PRIMARY);
+		test_plane_rotation(&data, IGT_PLANE_PRIMARY, false);
+	}
+	igt_subtest_f("primary-rotation-90-test-only") {
+		igt_require(gen >= 9);
+		data.rotation = IGT_ROTATION_90;
+		test_plane_rotation(&data, IGT_PLANE_PRIMARY, true);
 	}
 
 	igt_subtest_f("primary-rotation-270") {
 		igt_require(gen >= 9);
 		data.rotation = IGT_ROTATION_270;
-		test_plane_rotation(&data, IGT_PLANE_PRIMARY);
+		test_plane_rotation(&data, IGT_PLANE_PRIMARY, false);
+	}
+	igt_subtest_f("primary-rotation-270-test-only") {
+		igt_require(gen >= 9);
+		data.rotation = IGT_ROTATION_270;
+		test_plane_rotation(&data, IGT_PLANE_PRIMARY, true);
 	}
 
 	igt_subtest_f("sprite-rotation-90") {
 		igt_require(gen >= 9);
 		data.rotation = IGT_ROTATION_90;
-		test_plane_rotation(&data, IGT_PLANE_2);
+		test_plane_rotation(&data, IGT_PLANE_2, false);
+	}
+	igt_subtest_f("sprite-rotation-90-test-only") {
+		igt_require(gen >= 9);
+		data.rotation = IGT_ROTATION_90;
+		test_plane_rotation(&data, IGT_PLANE_2, true);
 	}
 
 	igt_subtest_f("sprite-rotation-270") {
 		igt_require(gen >= 9);
 		data.rotation = IGT_ROTATION_270;
-		test_plane_rotation(&data, IGT_PLANE_2);
+		test_plane_rotation(&data, IGT_PLANE_2, false);
+	}
+	igt_subtest_f("sprite-rotation-270-test-only") {
+		igt_require(gen >= 9);
+		data.rotation = IGT_ROTATION_270;
+		test_plane_rotation(&data, IGT_PLANE_2, true);
 	}
 
 	igt_subtest_f("sprite-rotation-90-pos-100-0") {
@@ -553,7 +677,14 @@ igt_main
 		data.rotation = IGT_ROTATION_90;
 		data.pos_x = 100,
 		data.pos_y = 0;
-		test_plane_rotation(&data, IGT_PLANE_2);
+		test_plane_rotation(&data, IGT_PLANE_2, false);
+	}
+	igt_subtest_f("sprite-rotation-90-pos-100-0-test-only") {
+		igt_require(gen >= 9);
+		data.rotation = IGT_ROTATION_90;
+		data.pos_x = 100,
+		data.pos_y = 0;
+		test_plane_rotation(&data, IGT_PLANE_2, true);
 	}
 
 	igt_subtest_f("bad-pixel-format") {
@@ -562,7 +693,15 @@ igt_main
 		data.pos_y = 0;
 		data.rotation = IGT_ROTATION_90;
 		data.override_fmt = DRM_FORMAT_RGB565;
-		test_plane_rotation(&data, IGT_PLANE_PRIMARY);
+		test_plane_rotation(&data, IGT_PLANE_PRIMARY, false);
+	}
+	igt_subtest_f("bad-pixel-format-test-only") {
+		igt_require(gen >= 9);
+		data.pos_x = 0,
+		data.pos_y = 0;
+		data.rotation = IGT_ROTATION_90;
+		data.override_fmt = DRM_FORMAT_RGB565;
+		test_plane_rotation(&data, IGT_PLANE_PRIMARY, true);
 	}
 
 	igt_subtest_f("bad-tiling") {
@@ -570,7 +709,14 @@ igt_main
 		data.override_fmt = 0;
 		data.rotation = IGT_ROTATION_90;
 		data.override_tiling = LOCAL_DRM_FORMAT_MOD_NONE;
-		test_plane_rotation(&data, IGT_PLANE_PRIMARY);
+		test_plane_rotation(&data, IGT_PLANE_PRIMARY, false);
+	}
+	igt_subtest_f("bad-tiling-test-only") {
+		igt_require(gen >= 9);
+		data.override_fmt = 0;
+		data.rotation = IGT_ROTATION_90;
+		data.override_tiling = LOCAL_DRM_FORMAT_MOD_NONE;
+		test_plane_rotation(&data, IGT_PLANE_PRIMARY, true);
 	}
 
 	igt_subtest_f("primary-rotation-90-flip-stress") {
@@ -578,18 +724,34 @@ igt_main
 		data.override_tiling = 0;
 		data.flip_stress = 60;
 		data.rotation = IGT_ROTATION_90;
-		test_plane_rotation(&data, IGT_PLANE_PRIMARY);
+		test_plane_rotation(&data, IGT_PLANE_PRIMARY, false);
+	}
+	igt_subtest_f("primary-rotation-90-flip-stress-test-only") {
+		igt_require(gen >= 9);
+		data.override_tiling = 0;
+		data.flip_stress = 60;
+		data.rotation = IGT_ROTATION_90;
+		test_plane_rotation(&data, IGT_PLANE_PRIMARY, true);
 	}
 
 	igt_subtest_f("primary-rotation-90-Y-tiled") {
 		igt_require(gen >= 9);
 		data.rotation = IGT_ROTATION_90;
-		test_plane_rotation_ytiled_obj(&data, IGT_PLANE_PRIMARY);
+		test_plane_rotation_ytiled_obj(&data, IGT_PLANE_PRIMARY, false);
+	}
+	igt_subtest_f("primary-rotation-90-Y-tiled-test-only") {
+		igt_require(gen >= 9);
+		data.rotation = IGT_ROTATION_90;
+		test_plane_rotation_ytiled_obj(&data, IGT_PLANE_PRIMARY, true);
 	}
 
 	igt_subtest_f("exhaust-fences") {
 		igt_require(gen >= 9);
-		test_plane_rotation_exhaust_fences(&data, IGT_PLANE_PRIMARY);
+		test_plane_rotation_exhaust_fences(&data, IGT_PLANE_PRIMARY, false);
+	}
+	igt_subtest_f("exhaust-fences-test-only") {
+		igt_require(gen >= 9);
+		test_plane_rotation_exhaust_fences(&data, IGT_PLANE_PRIMARY, true);
 	}
 
 	igt_fixture {
