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
|
// Copyright 2016 Yahoo Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
package com.yahoo.searchdefinition;
import com.yahoo.config.model.application.provider.BaseDeployLogger;
import com.yahoo.searchdefinition.derived.AttributeFields;
import com.yahoo.searchdefinition.derived.RawRankProfile;
import com.yahoo.searchdefinition.parser.ParseException;
import org.junit.Test;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import static org.junit.Assert.assertEquals;
/**
* @author <a href="mailto:bratseth@yahoo-inc.com">Jon Bratseth</a>
*/
public class RankingExpressionInliningTestCase extends SearchDefinitionTestCase {
@Test
public void testConstants() throws ParseException {
RankProfileRegistry rankProfileRegistry = new RankProfileRegistry();
SearchBuilder builder = new SearchBuilder(rankProfileRegistry);
builder.importString(
"search test {\n" +
" document test { \n" +
" field a type string { \n" +
" indexing: index \n" +
" }\n" +
" }\n" +
" \n" +
" rank-profile parent {\n" +
" constants {\n" +
" p1: 7 \n" +
" p2: 0 \n" +
" }\n" +
" first-phase {\n" +
" expression: p1 + foo\n" +
" }\n" +
" second-phase {\n" +
" expression: p2 * foo\n" +
" }\n" +
" macro inline foo() {\n" +
" expression: 3 + p1 + p2\n" +
" }\n" +
" }\n" +
" rank-profile child inherits parent {\n" +
" first-phase {\n" +
" expression: p1 + foo + baz + bar + arg(4.0)\n" +
" }\n" +
" constants {\n" +
" p2: 2.0 \n" +
" }\n" +
" macro bar() {\n" +
" expression: p2*p1\n" +
" }\n" +
" macro inline baz() {\n" +
" expression: p2+p1+boz\n" +
" }\n" +
" macro inline boz() {\n" +
" expression: 3.0\n" +
" }\n" +
" macro inline arg(a1) {\n" +
" expression: a1*2\n" +
" }\n" +
" }\n" +
"\n" +
"}\n");
builder.build();
Search s = builder.getSearch();
RankProfile parent = rankProfileRegistry.getRankProfile(s, "parent").compile();
assertEquals("17.0", parent.getFirstPhaseRanking().getRoot().toString());
assertEquals("0.0", parent.getSecondPhaseRanking().getRoot().toString());
List<Map.Entry<String, Object>> parentRankProperties = new ArrayList<>(new RawRankProfile(parent, new AttributeFields(s)).configProperties().entrySet());
assertEquals("rankingExpression(foo).rankingScript.part0=10.0", parentRankProperties.get(0).toString());
assertEquals("rankingExpression(firstphase).rankingScript=17.0", parentRankProperties.get(2).toString());
assertEquals("rankingExpression(secondphase).rankingScript=0.0", parentRankProperties.get(4).toString());
RankProfile child = rankProfileRegistry.getRankProfile(s, "child").compile();
assertEquals("31.0 + bar + arg(4.0)", child.getFirstPhaseRanking().getRoot().toString());
assertEquals("24.0", child.getSecondPhaseRanking().getRoot().toString());
List<Map.Entry<String, Object>> childRankProperties = new ArrayList<>(new RawRankProfile(child, new AttributeFields(s)).configProperties().entrySet());
for (Object o : childRankProperties) System.out.println(o);
assertEquals("rankingExpression(foo).rankingScript.part0=12.0", childRankProperties.get(0).toString());
assertEquals("rankingExpression(bar).rankingScript.part1=14.0", childRankProperties.get(1).toString());
assertEquals("rankingExpression(boz).rankingScript.part2=3.0", childRankProperties.get(2).toString());
assertEquals("rankingExpression(baz).rankingScript.part3=9.0 + rankingExpression(boz)", childRankProperties.get(3).toString());
assertEquals("rankingExpression(arg).rankingScript.part4=a1 * 2", childRankProperties.get(4).toString());
assertEquals("rankingExpression(firstphase).rankingScript=31.0 + rankingExpression(bar) + rankingExpression(arg@)", censorBindingHash(childRankProperties.get(7).toString()));
assertEquals("rankingExpression(secondphase).rankingScript=24.0", childRankProperties.get(9).toString());
}
/**
* Expression evaluation has no stack so macro arguments are bound at config time creating a separate version of
* each macro for each binding, using hashes to name the bound variants of the macro.
* This method censors those hashes for string comparison.
*/
private String censorBindingHash(String s) {
StringBuilder b = new StringBuilder();
boolean areInHash = false;
for (int i = 0; i < s.length() ; i++) {
char current = s.charAt(i);
if ( ! Character.isLetterOrDigit(current)) // end of hash
areInHash = false;
if ( ! areInHash)
b.append(current);
if (current == '@') // start of hash
areInHash = true;
}
return b.toString();
}
}
|