1package regexp2
2
3import "testing"
4
5func TestRE2CompatCapture(t *testing.T) {
6	r := MustCompile(`re(?P<a>2)`, RE2)
7	if m, err := r.FindStringMatch("blahre2blah"); m == nil {
8		t.Fatal("Expected match")
9	} else if err != nil {
10		t.Fatalf("Unexpected error: %v", err)
11	} else {
12		g := m.GroupByName("a")
13		if want, got := "2", g.String(); want != got {
14			t.Fatalf("Wanted %v got %v", want, got)
15		}
16	}
17}
18
19func TestRE2CompatCapture_Invalid(t *testing.T) {
20	bogus := []string{
21		`(?P<name>a`,
22		`(?P<name>`,
23		`(?P<name`,
24		`(?P<x y>a)`,
25		`(?P<>a)`,
26	}
27	for _, inp := range bogus {
28		t.Run(inp, func(t *testing.T) {
29			r, err := Compile(inp, RE2)
30			if err == nil {
31				t.Fatal("Expected failure to parse")
32			}
33			if r != nil {
34				t.Fatal("expected regexp to be nil")
35			}
36		})
37	}
38}
39
40func TestRE2NamedAscii(t *testing.T) {
41	table := []struct {
42		nm  string
43		pos string
44		neg string
45	}{
46		{nm: "alnum", pos: "1", neg: "!"},
47		{nm: "alpha", pos: "g", neg: "0"},
48		{nm: "blank", pos: " ", neg: "_"},
49		{nm: "ascii", pos: "*", neg: "\x8f"},
50		{nm: "cntrl", pos: "\t", neg: "A"},
51		{nm: "graph", pos: "!", neg: " "},
52		{nm: "lower", pos: "a", neg: "A"},
53		{nm: "print", pos: " ", neg: "\r"},
54		{nm: "punct", pos: "@", neg: "A"},
55		{nm: "space", pos: " ", neg: "A"},
56		{nm: "digit", pos: "1", neg: "A"},
57		{nm: "upper", pos: "A", neg: "a"},
58		{nm: "word", pos: "_", neg: "-"},
59		{nm: "xdigit", pos: "A", neg: "G"},
60	}
61
62	for _, row := range table {
63		t.Run(row.nm, func(t *testing.T) {
64			r := MustCompile(`[[:`+row.nm+`:]]`, RE2)
65			if m, _ := r.MatchString(row.pos); !m {
66				t.Fatal("Expected match")
67			}
68			if m, _ := r.MatchString(row.neg); m {
69				t.Fatal("Expected no match")
70			}
71		})
72		t.Run(row.nm+" negate", func(t *testing.T) {
73			r := MustCompile(`[[:^`+row.nm+`:]]`, RE2)
74			if m, _ := r.MatchString(row.neg); !m {
75				t.Fatal("Expected match")
76			}
77			if m, _ := r.MatchString(row.pos); m {
78				t.Fatal("Expected no match")
79			}
80		})
81	}
82
83}
84func TestRE2NamedAscii_Concat(t *testing.T) {
85	r := MustCompile(`[[:digit:]a]`, RE2)
86	if m, _ := r.MatchString("b"); m {
87		t.Fatal("Expected no match")
88	}
89	if m, _ := r.MatchString("a"); !m {
90		t.Fatal("Expected match")
91	}
92	if m, _ := r.MatchString("["); m {
93		t.Fatal("Expected no match")
94	}
95	if m, _ := r.MatchString("5"); !m {
96		t.Fatal("Expected match")
97	}
98}
99
100func TestRE2Dollar_Singleline(t *testing.T) {
101	// PCRE allows for \n after the $ and RE2 doesn't
102	r := MustCompile(`^ac$\n`, RE2)
103	if m, _ := r.MatchString("ac"); m {
104		t.Fatal("Expected no match")
105	}
106	if m, _ := r.MatchString("ac\n"); m {
107		t.Fatal("Expected no match")
108	}
109}
110
111func TestRE2Dollar_Multiline(t *testing.T) {
112	r := MustCompile(`^ac$\n`, RE2|Multiline)
113	if m, _ := r.MatchString("ac"); m {
114		t.Fatal("Expected no match")
115	}
116	if m, err := r.MatchString("ac\n"); err != nil {
117		t.Fatal(err)
118	} else if !m {
119		t.Fatal("Expected match")
120	}
121}
122