-
Notifications
You must be signed in to change notification settings - Fork 1
/
scanner_test.cc
148 lines (133 loc) · 4.92 KB
/
scanner_test.cc
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
// Copyright 2020 The Chromium OS Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "foomatic_shell/grammar.h"
#include "foomatic_shell/scanner.h"
#include <gtest/gtest.h>
#include <string>
#include <vector>
namespace foomatic_shell {
namespace {
// This function takes the input script as |input| and a sequence of tokens
// produced by a scanner (|tokens|). It generates and returns the string
// representation of the generated tokens. The returned string has the same
// length as |input|. The corresponding characters are set depending on the
// type of token covering given range according to the following rules:
// - 'B' - Byte
// - 'E' - ExecutedString
// - 'I' - InterpretedString
// - 'L' - LiteralString
// - 'S' - Space
// Positions that do not belong to any token are set to spaces.
// Example:
// - input string : abcde'rft' "dsfds"; `aaa` | bbb
// - representation: NNNNN LLL SS IIIII BS EEE SBSNNN
//
// The returned representation is calculated from |tokens|, not from |input|.
// The |input| string must be a reference to the same string as given to the
// scanner that produced |tokens|.
std::string CreateTokensRepresentation(const std::string& input,
const std::vector<Token>& tokens) {
std::string out(input.size(), ' ');
for (const Token& token : tokens) {
char c = 'x';
switch (token.type) {
case Token::Type::kByte:
c = 'B';
break;
case Token::Type::kExecutedString:
c = 'E';
break;
case Token::Type::kInterpretedString:
c = 'I';
break;
case Token::Type::kLiteralString:
c = 'L';
break;
case Token::Type::kNativeString:
c = 'N';
break;
case Token::Type::kSpace:
c = 'S';
break;
default:
break;
}
const size_t begin = token.begin - input.begin();
const size_t end = token.end - input.begin();
for (size_t i = begin; i < end; ++i)
out[i] = c;
}
return out;
}
TEST(Scanner, StringTypes) {
const std::string input = "command 'lit str' `exe str` \"int str\" nat str";
const std::string types = "NNNNNNNS LLLLLLL S EEEEEEE SS IIIIIII SNNNSNNN";
Scanner scanner(input);
std::vector<Token> tokens;
EXPECT_TRUE(scanner.ParseWholeInput(&tokens));
EXPECT_EQ(types, CreateTokensRepresentation(input, tokens));
}
TEST(Scanner, ExecutedStringInsideInterpretedString) {
const std::string input = "command \"int str1`exe str`int str2\" ";
const std::string types = "NNNNNNNS IIIIIIII EEEEEEE IIIIIIII SS";
Scanner scanner(input);
std::vector<Token> tokens;
EXPECT_TRUE(scanner.ParseWholeInput(&tokens));
EXPECT_EQ(types, CreateTokensRepresentation(input, tokens));
}
TEST(Scanner, UnterminatedLiteralString) {
const std::string input = "command 'int str1`exe str`int s";
Scanner scanner(input);
std::vector<Token> tokens;
EXPECT_FALSE(scanner.ParseWholeInput(&tokens));
EXPECT_EQ(scanner.GetPosition(), input.end());
}
TEST(Scanner, UnterminatedInterpretedString) {
const std::string input = "command \"int str1`exe str`int s";
Scanner scanner(input);
std::vector<Token> tokens;
EXPECT_FALSE(scanner.ParseWholeInput(&tokens));
EXPECT_EQ(scanner.GetPosition(), input.end());
}
TEST(Scanner, UnterminatedExecutedString) {
const std::string input = "command 'int str1' `exe str";
Scanner scanner(input);
std::vector<Token> tokens;
EXPECT_FALSE(scanner.ParseWholeInput(&tokens));
EXPECT_EQ(scanner.GetPosition(), input.end());
}
TEST(Scanner, CommandWithParameters) {
const std::string input =
"pdftops '9195' 'root' 'split_streams.pdf' '1' "
"' finishings=3 number-up=1 document=split.pdf' '/cups/tmp/foo-B65TL1'";
const std::string types =
"NNNNNNNS LLLL S LLLL S LLLLLLLLLLLLLLLLL S L S"
" LLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLL S LLLLLLLLLLLLLLLLLLLL ";
std::vector<Token> tokens;
Scanner scanner(input);
EXPECT_TRUE(scanner.ParseWholeInput(&tokens));
EXPECT_EQ(types, CreateTokensRepresentation(input, tokens));
}
TEST(Scanner, Pipeline) {
const std::string input = "ls -h | grep 'XXX' | wc -l; echo \"Done\"; ";
const std::string types = "NNSNNSBSNNNNS LLL SBSNNSNNBSNNNNS IIII BS";
std::vector<Token> tokens;
Scanner scanner(input);
EXPECT_TRUE(scanner.ParseWholeInput(&tokens));
EXPECT_EQ(types, CreateTokensRepresentation(input, tokens));
}
TEST(Scanner, Subshell) {
const std::string input =
"VAR1='xx' VAR=acs'zzz'qq my_app -par1 par2'qqq'"
" ; (echo ttt | tr t T; echo Done) | cat myfile.txt";
const std::string types =
"NNNNB LL SNNNBNNN LLL NNSSNNNNNNSSNNNNNSNNNN LLL "
"SBSBNNNNSNNNSBSNNSNSNBSNNNNSNNNNBSBSNNNSNNNNNNNNNN";
std::vector<Token> tokens;
Scanner scanner(input);
EXPECT_TRUE(scanner.ParseWholeInput(&tokens));
EXPECT_EQ(types, CreateTokensRepresentation(input, tokens));
}
} // namespace
} // namespace foomatic_shell