@@ -86,7 +86,61 @@ public function testQueryTimeout(): void
8686 }
8787 }
8888
89+ public function testCountTimeout (): void
90+ {
91+ if (!$ this ->getDatabase ()->getAdapter ()->getSupportForTimeouts ()) {
92+ $ this ->expectNotToPerformAssertions ();
93+ return ;
94+ }
95+
96+ /** @var Database $database */
97+ $ database = $ this ->getDatabase ();
98+
99+ $ database ->createCollection ('count-timeouts ' );
100+
101+ $ this ->assertEquals (
102+ true ,
103+ $ database ->createAttribute (
104+ collection: 'count-timeouts ' ,
105+ id: 'longtext ' ,
106+ type: Database::VAR_STRING ,
107+ size: 100000000 ,
108+ required: true
109+ )
110+ );
89111
112+ $ longtext = file_get_contents (__DIR__ . '/../../../resources/longtext.txt ' );
113+ for ($ i = 0 ; $ i < 20 ; $ i ++) {
114+ $ database ->createDocument ('count-timeouts ' , new Document ([
115+ 'longtext ' => $ longtext ,
116+ '$permissions ' => [
117+ Permission::read (Role::any ()),
118+ Permission::update (Role::any ()),
119+ Permission::delete (Role::any ())
120+ ]
121+ ]));
122+ }
123+
124+ try {
125+ $ database ->setTimeout (1 );
126+
127+ $ thrown = null ;
128+ try {
129+ // A substring scan forces the engine to walk every huge value; a
130+ // cheap filter (e.g. notEqual) lets COUNT finish inside the timeout.
131+ $ database ->count ('count-timeouts ' , [
132+ Query::contains ('longtext ' , ['needle-that-does-not-exist ' ]),
133+ ]);
134+ } catch (\Exception $ e ) {
135+ $ thrown = $ e ;
136+ }
137+
138+ $ this ->assertInstanceOf (TimeoutException::class, $ thrown , 'count() must throw a timeout exception ' );
139+ } finally {
140+ $ database ->clearTimeout ();
141+ $ database ->deleteCollection ('count-timeouts ' );
142+ }
143+ }
90144
91145 public function testPreserveDatesUpdate (): void
92146 {
0 commit comments