diff --git a/test/debayer-geometry.cpp b/test/debayer-geometry.cpp
index 27458aa1..86d4248f 100644
--- a/test/debayer-geometry.cpp
+++ b/test/debayer-geometry.cpp
@@ -2,7 +2,7 @@
 /*
  * Copyright (C) 2026, Red Hat Inc.
  *
- * Debayer projection tests
+ * Debayer projection and sensor crop tests
  */
 
 #include <array>
@@ -23,7 +23,7 @@ class DebayerGeometryTest : public Test
 protected:
 	int run() override
 	{
-		if (testProjection())
+		if (testProjection() || testCrop())
 			return TestFail;
 
 		return TestPass;
@@ -91,6 +91,38 @@ private:
 
 		return TestPass;
 	}
+
+	int testCrop()
+	{
+		static const struct {
+			Size input;
+			Size native;
+			Size output;
+			Rectangle expected;
+		} cases[] = {
+			{ { 1920, 1080 }, { 1920, 1080 }, { 1920, 1080 }, { 0, 0, 1920, 1080 } },
+			{ { 1928, 1092 }, { 1920, 1092 }, { 1920, 1092 }, { 4, 0, 1920, 1092 } },
+			/* Output resolution changes must not shrink the sensor window. */
+			{ { 1928, 1092 }, { 1920, 1092 }, { 1920, 1080 }, { 4, 6, 1920, 1080 } },
+			{ { 1928, 1092 }, { 1920, 1092 }, { 1280, 720 }, { 4, 6, 1920, 1080 } },
+			{ { 1928, 1092 }, { 1920, 1092 }, { 640, 480 }, { 236, 0, 1456, 1092 } },
+			{ { 1928, 1092 }, { 1920, 1092 }, { 512, 768 }, { 600, 0, 728, 1092 } },
+			{ { 1928, 1092 }, { 1920, 1092 }, { 1280, 640 }, { 4, 66, 1920, 960 } },
+			/* A smaller Bayer border leaves an odd top coordinate. */
+			{ { 1928, 1092 }, { 1924, 1092 }, { 1280, 720 }, { 2, 5, 1924, 1082 } },
+		};
+
+		for (const auto &entry : cases) {
+			Rectangle crop = debayerCrop(entry.input, entry.native, entry.output);
+			if (crop != entry.expected) {
+				std::cerr << "Crop " << entry.input << " -> " << entry.output
+					  << " is " << crop << ", expected " << entry.expected << std::endl;
+				return TestFail;
+			}
+		}
+
+		return TestPass;
+	}
 };
 
 TEST_REGISTER(DebayerGeometryTest)
