[NUI] Rebase develnui (DevelNUI only patches --> master) (#3910)
[platform/core/csapi/tizenfx.git] / test / Tizen.NUI.Devel.Tests.Ubuntu / nunit.framework / Common / TestSelectionParser.cs
1 // ***********************************************************************
2 // Copyright (c) 2015 Charlie Poole
3 //
4 // Permission is hereby granted, free of charge, to any person obtaining
5 // a copy of this software and associated documentation files (the
6 // "Software"), to deal in the Software without restriction, including
7 // without limitation the rights to use, copy, modify, merge, publish,
8 // distribute, sublicense, and/or sell copies of the Software, and to
9 // permit persons to whom the Software is furnished to do so, subject to
10 // the following conditions:
11 // 
12 // The above copyright notice and this permission notice shall be
13 // included in all copies or substantial portions of the Software.
14 // 
15 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
19 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
20 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
21 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22 // ***********************************************************************
23 #define PORTABLE
24 #define TIZEN
25 #define NUNIT_FRAMEWORK
26 #define NUNITLITE
27 #define NET_4_5
28 #define PARALLEL
29 using System;
30 using System.Collections.Generic;
31 using System.Text;
32
33 // Missing XML Docs
34 #pragma warning disable 1591
35
36 #if NUNIT_ENGINE
37 namespace NUnit.Engine
38 #else
39 namespace NUnit.Common
40 #endif
41 {
42     public class TestSelectionParser
43     {
44         private Tokenizer _tokenizer;
45
46         private static readonly Token LPAREN = new Token(TokenKind.Symbol, "(");
47         private static readonly Token RPAREN = new Token(TokenKind.Symbol, ")");
48         private static readonly Token AND_OP1 = new Token(TokenKind.Symbol, "&");
49         private static readonly Token AND_OP2 = new Token(TokenKind.Symbol, "&&");
50         private static readonly Token AND_OP3 = new Token(TokenKind.Word, "and");
51         private static readonly Token AND_OP4 = new Token(TokenKind.Word, "AND");
52         private static readonly Token OR_OP1 = new Token(TokenKind.Symbol, "|");
53         private static readonly Token OR_OP2 = new Token(TokenKind.Symbol, "||");
54         private static readonly Token OR_OP3 = new Token(TokenKind.Word, "or");
55         private static readonly Token OR_OP4 = new Token(TokenKind.Word, "OR");
56         private static readonly Token NOT_OP = new Token(TokenKind.Symbol, "!");
57
58         private static readonly Token EQ_OP1 = new Token(TokenKind.Symbol, "=");
59         private static readonly Token EQ_OP2 = new Token(TokenKind.Symbol, "==");
60         private static readonly Token NE_OP = new Token(TokenKind.Symbol, "!=");
61         private static readonly Token MATCH_OP = new Token(TokenKind.Symbol, "=~");
62         private static readonly Token NOMATCH_OP = new Token(TokenKind.Symbol, "!~");
63
64         private static readonly Token[] AND_OPS = new Token[] { AND_OP1, AND_OP2, AND_OP3, AND_OP4 };
65         private static readonly Token[] OR_OPS = new Token[] { OR_OP1, OR_OP2, OR_OP3, OR_OP4 };
66         private static readonly Token[] EQ_OPS = new Token[] { EQ_OP1, EQ_OP2 };
67         private static readonly Token[] REL_OPS = new Token[] { EQ_OP1, EQ_OP2, NE_OP, MATCH_OP, NOMATCH_OP };
68
69         private static readonly Token EOF = new Token(TokenKind.Eof);
70
71         public string Parse(string input)
72         {
73             _tokenizer = new Tokenizer(input);
74
75             if (_tokenizer.LookAhead == EOF)
76                 throw new TestSelectionParserException("No input provided for test selection.");
77
78             var result = ParseFilterExpression();
79
80             Expect(EOF);
81             return result;
82         }
83
84         /// <summary>
85         /// Parse a single term or an or expression, returning the xml
86         /// </summary>
87         /// <returns></returns>
88         public string ParseFilterExpression()
89         {
90             var terms = new List<string>();
91             terms.Add(ParseFilterTerm());
92
93             while (LookingAt(OR_OPS))
94             {
95                 NextToken();
96                 terms.Add(ParseFilterTerm());
97             }
98
99             if (terms.Count == 1)
100                 return terms[0];
101
102             var sb = new StringBuilder("<or>");
103
104             foreach (string term in terms)
105                 sb.Append(term);
106
107             sb.Append("</or>");
108
109             return sb.ToString();
110         }
111
112         /// <summary>
113         /// Parse a single element or an and expression and return the xml
114         /// </summary>
115         public string ParseFilterTerm()
116         {
117             var elements = new List<string>();
118             elements.Add(ParseFilterElement());
119
120             while (LookingAt(AND_OPS))
121             {
122                 NextToken();
123                 elements.Add(ParseFilterElement());
124             }
125
126             if (elements.Count == 1)
127                 return elements[0];
128
129             var sb = new StringBuilder("<and>");
130
131             foreach (string element in elements)
132                 sb.Append(element);
133
134             sb.Append("</and>");
135
136             return sb.ToString();
137         }
138
139         /// <summary>
140         /// Parse a single filter element such as a category expression
141         /// and return the xml representation of the filter.
142         /// </summary>
143         public string ParseFilterElement()
144         {
145             if (LookingAt(LPAREN, NOT_OP))
146                 return ParseExpressionInParentheses();
147
148             Token lhs = Expect(TokenKind.Word);
149
150             switch (lhs.Text)
151             {
152                 case "id":
153                 case "cat":
154                 case "method":
155                 case "class":
156                 case "name":
157                 case "test":
158                     Token op = lhs.Text == "id"
159                         ? Expect(EQ_OPS)
160                         : Expect(REL_OPS);
161                     Token rhs = Expect(TokenKind.String, TokenKind.Word);
162                     return EmitFilterElement(lhs, op, rhs);
163
164                 default:
165                     // Assume it's a property name
166                     op = Expect(REL_OPS);
167                     rhs = Expect(TokenKind.String, TokenKind.Word);
168                     return EmitPropertyElement(lhs, op, rhs);
169                     //throw InvalidTokenError(lhs);
170             }
171         }
172
173         private static string EmitFilterElement(Token lhs, Token op, Token rhs)
174         {
175             string fmt = null;
176
177             if (op == EQ_OP1 || op == EQ_OP2)
178                 fmt = "<{0}>{1}</{0}>";
179             else if (op == NE_OP)
180                 fmt = "<not><{0}>{1}</{0}></not>";
181             else if (op == MATCH_OP)
182                 fmt = "<{0} re='1'>{1}</{0}>";
183             else if (op == NOMATCH_OP)
184                 fmt = "<not><{0} re='1'>{1}</{0}></not>";
185             else
186                 fmt = "<{0} op='" + op.Text + "'>{1}</{0}>";
187
188             return EmitElement(fmt, lhs, rhs);
189         }
190
191         private static string EmitPropertyElement(Token lhs, Token op, Token rhs)
192         {
193             string fmt = null;
194
195             if (op == EQ_OP1 || op == EQ_OP2)
196                 fmt = "<prop name='{0}'>{1}</prop>";
197             else if (op == NE_OP)
198                 fmt = "<not><prop name='{0}'>{1}</prop></not>";
199             else if (op == MATCH_OP)
200                 fmt = "<prop name='{0}' re='1'>{1}</prop>";
201             else if (op == NOMATCH_OP)
202                 fmt = "<not><prop name='{0}' re='1'>{1}</prop></not>";
203             else
204                 fmt = "<prop name='{0}' op='" + op.Text + "'>{1}</prop>";
205
206             return EmitElement(fmt, lhs, rhs);
207         }
208
209         private static string EmitElement(string fmt, Token lhs, Token rhs)
210         {
211             return string.Format(fmt, lhs.Text, XmlEscape(rhs.Text));
212         }
213
214         private string ParseExpressionInParentheses()
215         {
216             Token op = Expect(LPAREN, NOT_OP);
217
218             if (op == NOT_OP) Expect(LPAREN);
219
220             string result = ParseFilterExpression();
221
222             Expect(RPAREN);
223
224             if (op == NOT_OP)
225                 result = "<not>" + result + "</not>";
226
227             return result;
228         }
229
230         // Require a token of one or more kinds
231         private Token Expect(params TokenKind[] kinds)
232         {
233             Token token = NextToken();
234
235             foreach (TokenKind kind in kinds)
236                 if (token.Kind == kind)
237                     return token;
238
239             throw InvalidTokenError(token);
240         }
241
242         // Require a token from a list of tokens
243         private Token Expect(params Token[] valid)
244         {
245             Token token = NextToken();
246
247             foreach (Token item in valid)
248                 if (token == item)
249                     return token;
250
251             throw InvalidTokenError(token);
252         }
253
254         private Exception InvalidTokenError(Token token)
255         {
256             return new TestSelectionParserException(string.Format(
257                 "Unexpected token '{0}' at position {1} in selection expression.", token.Text, token.Pos));
258         }
259
260         private Token LookAhead
261         {
262             get { return _tokenizer.LookAhead; }
263         }
264
265         private bool LookingAt(params Token[] tokens)
266         {
267             foreach (Token token in tokens)
268                 if (LookAhead == token)
269                     return true;
270
271             return false;
272         }
273
274         private Token NextToken()
275         {
276             return _tokenizer.NextToken();
277         }
278
279         private static string XmlEscape(string text)
280         {
281             return text
282                 .Replace("&", "&amp;")
283                 .Replace("\"", "&quot;")
284                 .Replace("<", "&lt;")
285                 .Replace(">", "&gt;")
286                 .Replace("'", "&apos;");
287         }
288     }
289 }