blob: d7d44bd17301a897041f70ff38fce1907c269179 [file] [log] [blame]
// Copyright 2015 Google Inc. All rights reserved
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// +build ignore
#include "find.h"
#include <unistd.h>
#include <string>
#include "fileutil.h"
#include "strutil.h"
int FindUnitTests();
int main(int argc, char* argv[]) {
if (argc == 1) {
return FindUnitTests();
}
InitFindEmulator();
string cmd;
for (int i = 1; i < argc; i++) {
if (i > 1)
cmd += ' ';
cmd += argv[i];
}
FindCommand fc;
if (!fc.Parse(cmd)) {
fprintf(stderr, "Find emulator does not support this command\n");
return 1;
}
string out;
if (!FindEmulator::Get()->HandleFind(cmd, fc, Loc(), &out)) {
fprintf(stderr, "Find emulator does not support this command\n");
return 1;
}
for (StringPiece tok : WordScanner(out)) {
printf("%.*s\n", SPF(tok));
}
}
string Run(const string& cmd) {
string s;
int ret = RunCommand("/bin/sh", "-c", cmd, RedirectStderr::NONE, &s);
if (ret != 0) {
fprintf(stderr, "Failed to run `%s`\n", cmd.c_str());
exit(ret);
}
return s;
}
static bool unit_test_failed = false;
void CompareFind(const string& cmd) {
string native = Run(cmd);
FindCommand fc;
if (!fc.Parse(cmd)) {
fprintf(stderr, "Find emulator cannot parse `%s`\n", cmd.c_str());
exit(1);
}
string emulated;
if (!FindEmulator::Get()->HandleFind(cmd, fc, Loc(), &emulated)) {
fprintf(stderr, "Find emulator cannot parse `%s`\n", cmd.c_str());
exit(1);
}
vector<StringPiece> nativeWords;
vector<StringPiece> emulatedWords;
WordScanner(native).Split(&nativeWords);
WordScanner(emulated).Split(&emulatedWords);
if (nativeWords != emulatedWords) {
fprintf(stderr, "Failed to match `%s`:\n", cmd.c_str());
auto nativeIter = nativeWords.begin();
auto emulatedIter = emulatedWords.begin();
fprintf(stderr, "%-20s %-20s\n", "Native:", "Emulated:");
while (nativeIter != nativeWords.end() ||
emulatedIter != emulatedWords.end()) {
fprintf(stderr, " %-20s %-20s\n",
(nativeIter == nativeWords.end())
? ""
: (*nativeIter++).as_string().c_str(),
(emulatedIter == emulatedWords.end())
? ""
: (*emulatedIter++).as_string().c_str());
}
fprintf(stderr, "------------------------------------------\n");
unit_test_failed = true;
}
}
void ExpectParseFailure(const string& cmd) {
Run(cmd);
FindCommand fc;
if (fc.Parse(cmd)) {
fprintf(stderr, "Expected parse failure for `%s`\n", cmd.c_str());
fprintf(stderr, "------------------------------------------\n");
unit_test_failed = true;
}
}
int FindUnitTests() {
Run("rm -rf out/find");
Run("mkdir -p out/find");
if (chdir("out/find")) {
perror("Failed to chdir(out/find)");
return 1;
}
// Set up files under out/find:
// drwxr-x--- top
// lrwxrwxrwx top/E -> missing
// lrwxrwxrwx top/C -> A
// -rw-r----- top/a
// drwxr-x--- top/A
// lrwxrwxrwx top/A/D -> B
// -rw-r----- top/A/b
// drwxr-x--- top/A/B
// -rw-r----- top/A/B/z
Run("mkdir -p top/A/B");
Run("cd top && ln -s A C");
Run("cd top/A && ln -s B D");
Run("cd top && ln -s missing E");
Run("touch top/a top/A/b top/A/B/z");
InitFindEmulator();
CompareFind("find .");
CompareFind("find -L .");
CompareFind("find top/C");
CompareFind("find top/C/.");
CompareFind("find -L top/C");
CompareFind("find -L top/C/.");
CompareFind("cd top && find C");
CompareFind("cd top && find -L C");
CompareFind("cd top/C && find .");
CompareFind("cd top/C && find D/./z");
CompareFind("find .//top");
CompareFind("find top -type f -name 'a*' -o -name \\*b");
CompareFind("find top \\! -name 'a*'");
CompareFind("find top \\( -name 'a*' \\)");
ExpectParseFailure("find top -name a\\*");
return unit_test_failed ? 1 : 0;
}