@@ -10,6 +10,7 @@ import (
1010 "net"
1111 "net/http"
1212 "net/http/httptest"
13+ urlpkg "net/url"
1314 "os"
1415 "strconv"
1516 "strings"
@@ -34,6 +35,7 @@ import (
3435 adminstore "github.com/umputun/remark42/backend/app/store/admin"
3536 "github.com/umputun/remark42/backend/app/store/engine"
3637 "github.com/umputun/remark42/backend/app/store/image"
38+ "github.com/umputun/remark42/backend/app/store/search"
3739 "github.com/umputun/remark42/backend/app/store/service"
3840)
3941
@@ -212,6 +214,94 @@ func TestRest_rejectAnonUser(t *testing.T) {
212214 assert .Equal (t , http .StatusOK , resp .StatusCode , "real user" )
213215}
214216
217+ func TestRest_Search (t * testing.T ) {
218+ var searchIndexPath string
219+ ts , _ , teardown := startupT (t , func (srv * Rest ) {
220+ var err error
221+ searchIndexPath , err = randomPath (srv .WebRoot , "test-search-remark" , "" )
222+ require .NoError (t , err )
223+ srv .DataService .SearchService , err = search .NewService ([]string {"remark42" }, search.ServiceParams {
224+ IndexPath : searchIndexPath ,
225+ Analyzer : "standard" ,
226+ })
227+ require .NoError (t , err )
228+ })
229+ defer teardown ()
230+ defer func () { _ = os .RemoveAll (searchIndexPath ) }()
231+
232+ t0 := time .Date (2018 , 12 , 20 , 15 , 18 , 22 , 0 , time .Local )
233+
234+ id1 := addComment (t , store.Comment {Text : "test test" , Timestamp : t0 .Add (1 * time .Minute ), Locator : store.Locator {SiteID : "remark42" , URL : "https://radio-t.com/abc" }}, ts )
235+ id2 := addComment (t , store.Comment {Text : "test hello" , Timestamp : t0 .Add (2 * time .Minute ), Locator : store.Locator {SiteID : "remark42" , URL : "https://radio-t.com/blah" }}, ts )
236+ id3 := addComment (t , store.Comment {Text : "hello world" , Timestamp : t0 .Add (3 * time .Minute ), Locator : store.Locator {SiteID : "remark42" , URL : "https://radio-t.com/blah" }}, ts )
237+ id4 := addComment (t , store.Comment {Text : "# title\n \n ok\n " , Timestamp : t0 .Add (4 * time .Minute ), Locator : store.Locator {SiteID : "remark42" , URL : "https://radio-t.com/blah" }}, ts )
238+
239+ idToPos := map [string ]int {id1 : 1 , id2 : 2 , id3 : 3 , id4 : 4 }
240+ tbl := []struct {
241+ query string
242+ extraParams string
243+ ids []int
244+ status int
245+ }{
246+ {"blah" , "" , []int {}, http .StatusOK },
247+ {"h1" , "" , []int {}, http .StatusOK },
248+ {"world" , "" , []int {3 }, http .StatusOK },
249+ {"title" , "" , []int {4 }, http .StatusOK },
250+ {"\" hello world\" " , "" , []int {3 }, http .StatusOK },
251+ {"test" , "&sort=time" , []int {1 , 2 }, http .StatusOK },
252+ {"hello" , "&sort=-time" , []int {3 , 2 }, http .StatusOK },
253+ {"hello world" , "&sort=time" , []int {2 , 3 }, http .StatusOK },
254+ {"hello world test" , "&sort=time" , []int {1 , 2 , 3 }, http .StatusOK },
255+ {"hello world test" , "&sort=time&skip=1" , []int {2 , 3 }, http .StatusOK },
256+ {"hello world test" , "&sort=time&skip=1&limit=1" , []int {2 }, http .StatusOK },
257+ {"" , "" , []int {}, http .StatusBadRequest },
258+ {"test" , "&sort=text" , []int {}, http .StatusBadRequest },
259+ {"test" , "&skip=-1" , []int {}, http .StatusBadRequest },
260+ {"test" , "&limit=999999" , []int {}, http .StatusBadRequest },
261+ }
262+
263+ cnt := 0
264+ for i , tt := range tbl {
265+ tt := tt
266+
267+ cnt ++
268+ if (cnt % 10 ) == 0 {
269+ // wait for rate limiter
270+ time .Sleep (1 * time .Second )
271+ }
272+ t .Run (strconv .Itoa (i ), func (t * testing.T ) {
273+ resp , err := http .Get (fmt .Sprintf ("%s/api/v1/search?site=remark42&query=%s%s" ,
274+ ts .URL , urlpkg .QueryEscape (tt .query ), tt .extraParams ))
275+ require .NoError (t , err )
276+
277+ defer resp .Body .Close ()
278+ body , err := io .ReadAll (resp .Body )
279+ require .NoError (t , err )
280+ assert .Equal (t , tt .status , resp .StatusCode )
281+
282+ result := commentsWithTotal {}
283+ err = json .Unmarshal (body , & result )
284+ require .NoError (t , err )
285+
286+ foundIds := make ([]int , len (result .Comments ))
287+ for i , c := range result .Comments {
288+ foundIds [i ] = idToPos [c .ID ]
289+ }
290+ require .Equal (t , tt .ids , foundIds )
291+ })
292+ }
293+ }
294+
295+ func TestRest_SearchDisabledFeature (t * testing.T ) {
296+ ts , _ , teardown := startupT (t )
297+ defer teardown ()
298+
299+ resp , err := http .Get (ts .URL + "/api/v1/search?site=remark42&query=test" )
300+ require .NoError (t , err )
301+ require .NoError (t , resp .Body .Close ())
302+ assert .Equal (t , http .StatusBadRequest , resp .StatusCode )
303+ }
304+
215305func Test_URLKey (t * testing.T ) {
216306 tbl := []struct {
217307 url string
@@ -633,5 +723,9 @@ func waitForHTTPSServerStart(port int) {
633723}
634724
635725func TestMain (m * testing.M ) {
636- goleak .VerifyTestMain (m )
726+ goleak .VerifyTestMain (m ,
727+ // we should call bleve.Config.Shutdown() to close all the workers,
728+ // but we don't do it for each server instance because it's global per application
729+ goleak .IgnoreTopFunction ("github.com/blevesearch/bleve_index_api.AnalysisWorker" ),
730+ )
637731}
0 commit comments