aboutsummaryrefslogtreecommitdiff
path: root/tests/Search/ParserTest.php
blob: 9a6aeef603d55c97839c4d904420790bac136e23 (plain)
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
<?php

namespace Micropoly\Search;

use PHPUnit\Framework\TestCase;

class ParserTest extends TestCase
{

    /**
     * @covers \Micropoly\Search\Parser::tokenize
     * @dataProvider tokenizeDataProvider
     */
    public function testTokenize($input, $want)
    {
        $have = [];
        foreach (Parser::tokenize($input) as $tok)
            $have[] = $tok;

        $this->assertSame($want, $have);
    }

    public function tokenizeDataProvider()
    {
        return [
            ["", []],
            ["hello", [
                [Parser::TOK_WORD, "hello"],
            ]],
            ["hello world", [
                [Parser::TOK_WORD, "hello"],
                [Parser::TOK_WORD, "world"],
            ]],
            ['"hello world"', [
                [Parser::TOK_WORD, "hello world"],
            ]],
            ['"hello\\"quote\\\\"', [
                [Parser::TOK_WORD , 'hello"quote\\'],
            ]],
            ["foo\\ bar", [
                [Parser::TOK_WORD, "foo bar"],
            ]],
            ['foo\\\\bar\\"baz', [
                [Parser::TOK_WORD, 'foo\\bar"baz'],
            ]],
            ['foo\\', [
                [Parser::TOK_WORD, 'foo\\'],
            ]],
            ["#foo #bar", [
                [Parser::TOK_TAG, "foo"],
                [Parser::TOK_TAG, "bar"],
            ]],
            ["#foo\\ bar", [
                [Parser::TOK_TAG, "foo bar"],
            ]],
            ["and or not ()( )", [
                [Parser::TOK_OP, "and"],
                [Parser::TOK_OP, "or"],
                [Parser::TOK_OP, "not"],
                [Parser::TOK_PAROPEN, null],
                [Parser::TOK_PARCLOSE, null],
                [Parser::TOK_PAROPEN, null],
                [Parser::TOK_PARCLOSE, null],
            ]],
            ["(#foo)", [
                [Parser::TOK_PAROPEN, null],
                [Parser::TOK_TAG, "foo"],
                [Parser::TOK_PARCLOSE, null],
            ]],
            ["foo:bar", [
                [Parser::TOK_PROP, "foo"],
                [Parser::TOK_WORD, "bar"],
            ]],
        ];
    }

    public function testTokenizeFailUnclosedString()
    {
        $this->expectException(ParseError::class);
        foreach (Parser::tokenize('foo "bar') as $_);
    }

    /**
     * @param string $input
     * @param bool|null|SearchExpr $exprOrFalseForErr
     * @dataProvider parseDataProvider
     */
    public function testParse(string $input, $exprOrFalseForErr)
    {
        if ($exprOrFalseForErr === false)
            $this->expectException(ParseError::class);

        $have = Parser::parse($input);
        if ($have !== null)
            $have = $have->toString();

        $want = $exprOrFalseForErr === null ? null : $exprOrFalseForErr->toString();

        $this->assertSame($want, $have);
    }

    public function parseDataProvider()
    {
        return [
            ["", null],
            ["(", false],
            [")", false],
            ["foo", new FTSExpr("foo")],
            ["foo #bar", new LogicOp(LogicOp::OP_AND, new FTSExpr("foo"), new TagExpr("bar"))],
            ["(foo and #bar) or not baz", new LogicOp(
                LogicOp::OP_OR, new LogicOp(
                LogicOp::OP_AND,
                new FTSExpr("foo"),
                new TagExpr("bar")
            ), new NotOp(new FTSExpr("baz"))
            )],
            ["foo bar", new FTSLogicOp(LogicOp::OP_AND, new FTSExpr("foo"), new FTSExpr("bar"))],
        ];
    }
}