aboutsummaryrefslogtreecommitdiffstats
path: root/container-search/src/test/java/com/yahoo/search/federation/vespa/test/VespaSearcherTestCase.java
blob: cc00c6739fa74ff01dbb11a1a8426869021f9984 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
// Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
package com.yahoo.search.federation.vespa.test;

import com.yahoo.prelude.query.*;
import com.yahoo.search.Query;
import com.yahoo.search.federation.vespa.VespaSearcher;
import com.yahoo.search.query.QueryTree;
import com.yahoo.search.query.parser.Parsable;
import com.yahoo.search.query.parser.Parser;
import com.yahoo.search.query.parser.ParserEnvironment;
import com.yahoo.search.query.parser.ParserFactory;
import com.yahoo.search.result.Hit;
import com.yahoo.search.searchchain.Execution;
import org.apache.http.HttpEntity;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;

import java.io.IOException;
import java.net.URI;

import static org.junit.Assert.assertEquals;

/**
 * Check query marshaling in VespaSearcher works.
 *
 * @author Steinar Knutsen
 */
public class VespaSearcherTestCase {

    private VespaSearcher searcher;

    @Before
    public void setUp() {
        searcher = new VespaSearcher("cache1","",0,"");
    }

    @After
    public void tearDown() {
        searcher.deconstruct();
    }

    @Test
    public void testMarshalQuery() {
        RankItem root = new RankItem();
        QueryTree r = new QueryTree(root);
        AndItem recall = new AndItem();
        PhraseItem usual = new PhraseItem();
        PhraseItem filterPhrase = new PhraseItem(new String[] {"bloody", "expensive"});
        WordItem filterWord = new WordItem("silly");

        filterPhrase.setFilter(true);
        filterWord.setFilter(true);

        root.addItem(recall);
        usual.addItem(new WordItem("new"));
        usual.addItem(new WordItem("york"));
        recall.addItem(usual);
        recall.addItem(new WordItem("shoes"));
        root.addItem(new WordItem("nike"));
        root.addItem(new WordItem("adidas"));
        root.addItem(filterPhrase);
        recall.addItem(filterWord);

        assertEquals("( \"new york\" AND shoes AND silly ) RANK nike RANK adidas RANK \"bloody expensive\"", searcher.marshalQuery(r));
    }

    @Test
    public void testMarshalQuerySmallTree() {
        RankItem root = new RankItem();
        QueryTree r = new QueryTree(root);
        AndItem recall = new AndItem();
        PhraseItem usual = new PhraseItem();
        PhraseItem filterPhrase = new PhraseItem(new String[] {"bloody", "expensive"});
        WordItem filterWord = new WordItem("silly");

        filterPhrase.setFilter(true);
        filterWord.setFilter(true);

        root.addItem(recall);
        usual.addItem(new WordItem("new"));
        usual.addItem(new WordItem("york"));
        recall.addItem(usual);
        recall.addItem(new WordItem("shoes"));
        root.addItem(filterPhrase);
        recall.addItem(filterWord);

        assertEquals("( \"new york\" AND shoes AND silly ) RANK \"bloody expensive\"", searcher.marshalQuery(r));
        // TODO: Switch to this 2-way check rather than just 1-way and then also make this actually treat filter terms correctly
        // assertMarshals(root)
    }

    @Test
    public void testWandMarshalling() {
        WeakAndItem root = new WeakAndItem();
        root.setN(32);
        root.addItem(new WordItem("a"));
        root.addItem(new WordItem("b"));
        root.addItem(new WordItem("c"));
        assertMarshals(root);
    }

    @Test
    public void testWandMarshalling2() {
        // AND (WAND(10) a!1 the!10) source:yahoonews
        AndItem root = new AndItem();
        WeakAndItem wand = new WeakAndItem(10);
        wand.addItem(newWeightedWordItem("a",1));
        wand.addItem(newWeightedWordItem("the",10));
        root.addItem(wand);
        root.addItem(new WordItem("yahoonews","source"));
        assertMarshals(root);
    }

    private WordItem newWeightedWordItem(String word,int weight) {
        WordItem wordItem=new WordItem(word);
        wordItem.setWeight(weight);
        return wordItem;
    }

    private void assertMarshals(Item root) {
        QueryTree r = new QueryTree(root);
        String marshalledQuery=searcher.marshalQuery(r);
        assertEquals("Marshalled form '" + marshalledQuery + "' recreates the original",
                     r,parseQuery(marshalledQuery,""));
    }

    private static Item parseQuery(String query, String filter) {
        Parser parser = ParserFactory.newInstance(Query.Type.ADVANCED, new ParserEnvironment());
        return parser.parse(new Parsable().setQuery(query).setFilter(filter));
    }

    @Test
    public void testSourceProviderProperties() throws Exception {
        /* TODO: update test
        Server httpServer = new Server();
        try {
            SocketConnector listener = new SocketConnector();
            listener.setHost("0.0.0.0");
            httpServer.addConnector(listener);
            httpServer.setHandler(new DummyHandler());
            httpServer.start();

            int port=httpServer.getConnectors()[0].getLocalPort();

            List<SourcesConfig.Source> sourcesConfig = new ArrayList<SourcesConfig.Source>();
            SourcesConfig.Source sourceConfig = new SourcesConfig.Source();
            sourceConfig.chain.setValue("news");
            sourceConfig.provider.setValue("news");
            sourceConfig.id.setValue("news");
            sourceConfig.timelimit.value = 10000;
            sourcesConfig.add(sourceConfig);
            FederationSearcher federator =
                    new FederationSearcher(ComponentId.createAnonymousComponentId(),
                            new ArrayList<SourcesConfig.Source>(sourcesConfig));
            SearchChain mainChain=new OrderedSearchChain(federator);

            SearchChainRegistry registry=new SearchChainRegistry();
            SearchChain sourceChain=new SearchChain(new ComponentId("news"),new VespaSearcher("test","localhost",port,""));
            registry.register(sourceChain);
            Query query=new Query("?query=hans&hits=20&provider.news.a=a1&source.news.b=b1");
            Result result=new Execution(mainChain,registry).search(query);
            assertNull(result.hits().getError());
            Hit testHit=result.hits().get("testHit");
            assertNotNull(testHit);
            assertEquals("testValue",testHit.fields().get("testField"));
            assertEquals("a1",testHit.fields().get("a"));
            assertEquals("b1",testHit.fields().get("b"));
        }
        finally {
            httpServer.stop();
        }
        */
    }

    @Test
    public void testVespaSearcher() {
        VespaSearcher v=new VespaSearcherValidatingSubclass();
        new Execution(v, Execution.Context.createContextStub()).search(new Query(com.yahoo.search.test.QueryTestCase.httpEncode("?query=test&filter=myfilter")));
    }

    private class VespaSearcherValidatingSubclass extends VespaSearcher {

        public VespaSearcherValidatingSubclass() {
            super("configId","host",80,"path");
        }

        @Override
        protected HttpEntity getEntity(URI uri, Hit requestMeta, Query query) throws IOException {
            assertEquals("http://host:80/path?query=test+RANK+myfilter&type=adv&offset=0&hits=10&presentation.format=xml",uri.toString());
            return super.getEntity(uri,requestMeta,query);
        }

    }

    //  used by the old testSourceProviderProperties()
//    private class DummyHandler extends AbstractHandler {
//        public void handle(String s, Request request, HttpServletRequest httpServletRequest,
//                           HttpServletResponse httpServletResponse) throws IOException, ServletException {
//
//            try {
//                Response httpResponse = httpServletResponse instanceof Response ? (Response) httpServletResponse : HttpConnection.getCurrentConnection().getResponse();
//
//                httpResponse.setStatus(HttpStatus.OK_200);
//                httpResponse.setContentType("text/xml");
//                httpResponse.setCharacterEncoding("UTF-8");
//                Result r=new Result(new Query());
//                Hit testHit=new Hit("testHit");
//                testHit.setField("uri","testHit"); // That this is necessary is quite unfortunate...
//                testHit.setField("testField","testValue");
//                // Write back all incoming properties:
//                for (Object e : httpServletRequest.getParameterMap().entrySet()) {
//                    Map.Entry entry=(Map.Entry)e;
//                    testHit.setField(entry.getKey().toString(),getFirstValue(entry.getValue()));
//                }
//
//                r.hits().add(testHit);
//
//                //StringWriter sw=new StringWriter();
//                //r.render(sw);
//                //System.out.println(sw.toString());
//
//                SearchRendererAdaptor.callRender(httpResponse.getWriter(), r);
//                httpResponse.complete();
//            }
//            catch (Exception e) {
//                System.out.println("WARNING: Could not respond to request: " + Exceptions.toMessageString(e));
//                e.printStackTrace();
//            }
//        }
//
//        private String getFirstValue(Object entry) {
//            if (entry instanceof String[])
//                return ((String[])entry)[0].toString();
//            else
//                return entry.toString();
//        }
//    }

}