diff --git a/.travis.yml b/.travis.yml index 1663ca5b9f..c3d5321e0c 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,32 +1,12 @@ +dist: trusty +sudo: false language: rust rust: - 1.12.0 - stable - beta - nightly -sudo: false -script: - - cargo build --verbose - - if [ "$TRAVIS_RUST_VERSION" = "nightly" ]; then - cargo build --verbose --manifest-path=regex-debug/Cargo.toml; - RUSTFLAGS="-C target-feature=+ssse3" cargo test --verbose --features 'simd-accel pattern' --jobs 2; - else - travis_wait cargo test --verbose --jobs 2; - fi - - ./run-shootout-test - - cargo doc --verbose - - cargo test --verbose --manifest-path=regex-syntax/Cargo.toml - - cargo doc --verbose --manifest-path=regex-syntax/Cargo.toml - - if [ "$TRAVIS_RUST_VERSION" = "nightly" ]; then - (cd regex-capi && cargo build --verbose); - (cd regex-capi/ctest && ./compile && LD_LIBRARY_PATH=../target/debug ./test); - (cd regex-capi/examples && ./compile && LD_LIBRARY_PATH=../target/release ./iter); - (cd bench && travis_wait ./run rust); - (cd bench && travis_wait ./run rust-bytes --no-run); - (cd bench && travis_wait ./run pcre1 --no-run); - (cd bench && travis_wait ./run onig --no-run); - travis_wait cargo test --verbose --manifest-path=regex_macros/Cargo.toml; - fi +script: ci/script.sh addons: apt: packages: @@ -34,20 +14,15 @@ addons: - libelf-dev - libdw-dev - binutils-dev -after_success: | - [ $TRAVIS_BRANCH = master ] && - [ $TRAVIS_PULL_REQUEST = false ] && - [ $TRAVIS_RUST_VERSION = nightly ] && - echo '' > target/doc/index.html && - pip install ghp-import --user $USER && - $HOME/.local/bin/ghp-import -n target/doc && - git push -qf https://${TOKEN}@github.com/${TRAVIS_REPO_SLUG}.git gh-pages && - wget https://github.com/SimonKagstrom/kcov/archive/master.tar.gz && - tar xzf master.tar.gz && mkdir kcov-master/build && cd kcov-master/build && cmake .. && make && make install DESTDIR=../tmp && cd ../.. && - PATH="./kcov-master/tmp/usr/local/bin:$PATH" ./run-kcov --coveralls-id $TRAVIS_JOB_ID + - wget + - clang-3.6 + - cmake + - python + - python-virtualenv +after_success: ci/after_success.sh env: global: - secure: "ii5NwZiArNTxFuVnjXDHrYutkp82116hqBbzsCv/v53O5gCn1GKbCRyusFYHjr+ytymEPKH171cAQ7doGt3QPyFs2jdzK6+xz4obwCBfAPwgbtuFu9P/lIasG1ja2i/2T61g12DSlzAVTCkLnHNTLad4FWsyDyqJLpY4I4JFvcE=" + secure: "GdGE0kFYiJGccVZligur7JlWRCy49eH6uWPl71mrnaaW8jLHmkva0jVb0LB9e5ol3YMaMCgrwM2pcj3Uk2C08YcGIoEKOLlDVho351KaD6XfclZ29CQTAPMz4Xut2IcB4YeuZlDrOnM26guTIOtn2NAjeQgOhpM/ErzVBgkB+wQ=" notifications: email: on_success: never diff --git a/Cargo.toml b/Cargo.toml index e115931aef..e11a3b4bf3 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -30,7 +30,7 @@ utf8-ranges = "1" # For examples. lazy_static = "0.2.2" # For property based tests. -quickcheck = "0.4.1" +quickcheck = { version = "0.4.1", default-features = false } # For generating random test data. rand = "0.3.15" diff --git a/appveyor.yml b/appveyor.yml index 6a1b8dc19c..0933ad8cc3 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -14,4 +14,4 @@ install: build: false test_script: - - cargo test --verbose + - cargo test --verbose --jobs 4 diff --git a/bench/Cargo.toml b/bench/Cargo.toml index 0bd686762a..8875fed487 100644 --- a/bench/Cargo.toml +++ b/bench/Cargo.toml @@ -14,7 +14,7 @@ build = "build.rs" docopt = "0.6" lazy_static = "0.1" libc = "0.2" -onig = { version = "0.4", optional = true } +onig = { version = "1.2", optional = true } libpcre-sys = { version = "0.2", optional = true } memmap = "0.2" regex = { version = "0.2.0", path = "..", features = ["simd-accel"] } diff --git a/bench/src/ffi/re2.h b/bench/src/ffi/re2.h index 4a8c5c8a7e..377a04d700 100644 --- a/bench/src/ffi/re2.h +++ b/bench/src/ffi/re2.h @@ -2,8 +2,8 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -#ifndef RE2_RE2_H -#define RE2_RE2_H +#ifndef RE2_RE2_H_ +#define RE2_RE2_H_ // C++ interface to the re2 regular-expression library. // RE2 supports Perl-style regular expressions (with extensions like @@ -179,23 +179,25 @@ // RE2::Octal(&a), RE2::Hex(&b), RE2::CRadix(&c), RE2::CRadix(&d)); // will leave 64 in a, b, c, and d. +#include #include +#include +#include #include #include #include + #include "re2/stringpiece.h" -#include "re2/variadic_function.h" -#ifndef RE2_HAVE_LONGLONG -#define RE2_HAVE_LONGLONG 1 -#endif +namespace re2 { +class Prog; +class Regexp; +} // namespace re2 namespace re2 { +// TODO(junyer): Get rid of this. using std::string; -using std::map; -class Prog; -class Regexp; // Interface for regular expression matching. Also corresponds to a // pre-compiled regular expression. An "RE2" object is safe for @@ -251,7 +253,7 @@ class RE2 { RE2(const string& pattern); #endif RE2(const StringPiece& pattern); - RE2(const StringPiece& pattern, const Options& option); + RE2(const StringPiece& pattern, const Options& options); ~RE2(); // Returns whether RE2 was created properly. @@ -281,7 +283,7 @@ class RE2 { // EXPERIMENTAL! SUBJECT TO CHANGE! // Outputs the program fanout as a histogram bucketed by powers of 2. // Returns the number of the largest non-empty bucket. - int ProgramFanout(map* histogram) const; + int ProgramFanout(std::map* histogram) const; // Returns the underlying Regexp; not for general use. // Returns entire_regexp_ so that callers don't need @@ -290,21 +292,21 @@ class RE2 { /***** The useful part: the matching interface *****/ - // Matches "text" against "pattern". If pointer arguments are + // Matches "text" against "re". If pointer arguments are // supplied, copies matched sub-patterns into them. // // You can pass in a "const char*" or a "string" for "text". - // You can pass in a "const char*" or a "string" or a "RE2" for "pattern". + // You can pass in a "const char*" or a "string" or a "RE2" for "re". // // The provided pointer arguments can be pointers to any scalar numeric // type, or one of: // string (matched piece is copied to string) // StringPiece (StringPiece is mutated to point to matched piece) - // T (where "bool T::ParseFrom(const char*, int)" exists) + // T (where "bool T::ParseFrom(const char*, size_t)" exists) // (void*)NULL (the corresponding matched sub-pattern is not copied) // // Returns true iff all of the following conditions are satisfied: - // a. "text" matches "pattern" exactly + // a. "text" matches "re" exactly // b. The number of matched sub-patterns is >= number of supplied pointers // c. The "i"th argument has a suitable type for holding the // string captured as the "i"th sub-pattern. If you pass in @@ -320,32 +322,65 @@ class RE2 { // RE2::FullMatch("abc", "[a-z]+(\\d+)?", &number); static bool FullMatchN(const StringPiece& text, const RE2& re, const Arg* const args[], int argc); - static const VariadicFunction2< - bool, const StringPiece&, const RE2&, Arg, RE2::FullMatchN> FullMatch; - // Exactly like FullMatch(), except that "pattern" is allowed to match + // Exactly like FullMatch(), except that "re" is allowed to match // a substring of "text". - static bool PartialMatchN(const StringPiece& text, const RE2& re, // 3..16 args + static bool PartialMatchN(const StringPiece& text, const RE2& re, const Arg* const args[], int argc); - static const VariadicFunction2< - bool, const StringPiece&, const RE2&, Arg, RE2::PartialMatchN> PartialMatch; - // Like FullMatch() and PartialMatch(), except that pattern has to - // match a prefix of "text", and "input" is advanced past the matched + // Like FullMatch() and PartialMatch(), except that "re" has to match + // a prefix of the text, and "input" is advanced past the matched // text. Note: "input" is modified iff this routine returns true. - static bool ConsumeN(StringPiece* input, const RE2& pattern, // 3..16 args + static bool ConsumeN(StringPiece* input, const RE2& re, const Arg* const args[], int argc); - static const VariadicFunction2< - bool, StringPiece*, const RE2&, Arg, RE2::ConsumeN> Consume; - - // Like Consume(..), but does not anchor the match at the beginning of the - // string. That is, "pattern" need not start its match at the beginning of - // "input". For example, "FindAndConsume(s, "(\\w+)", &word)" finds the next - // word in "s" and stores it in "word". - static bool FindAndConsumeN(StringPiece* input, const RE2& pattern, - const Arg* const args[], int argc); - static const VariadicFunction2< - bool, StringPiece*, const RE2&, Arg, RE2::FindAndConsumeN> FindAndConsume; + + // Like Consume(), but does not anchor the match at the beginning of + // the text. That is, "re" need not start its match at the beginning + // of "input". For example, "FindAndConsume(s, "(\\w+)", &word)" finds + // the next word in "s" and stores it in "word". + static bool FindAndConsumeN(StringPiece* input, const RE2& re, + const Arg* const args[], int argc); + +#ifndef SWIG + private: + template + static inline bool Apply(F f, SP sp, const RE2& re) { + return f(sp, re, NULL, 0); + } + + template + static inline bool Apply(F f, SP sp, const RE2& re, const A&... a) { + const Arg* const args[] = {&a...}; + const int argc = sizeof...(a); + return f(sp, re, args, argc); + } + + public: + // In order to allow FullMatch() et al. to be called with a varying number + // of arguments of varying types, we use two layers of variadic templates. + // The first layer constructs the temporary Arg objects. The second layer + // (above) constructs the array of pointers to the temporary Arg objects. + + template + static bool FullMatch(const StringPiece& text, const RE2& re, A&&... a) { + return Apply(FullMatchN, text, re, Arg(std::forward(a))...); + } + + template + static bool PartialMatch(const StringPiece& text, const RE2& re, A&&... a) { + return Apply(PartialMatchN, text, re, Arg(std::forward(a))...); + } + + template + static bool Consume(StringPiece* input, const RE2& re, A&&... a) { + return Apply(ConsumeN, input, re, Arg(std::forward(a))...); + } + + template + static bool FindAndConsume(StringPiece* input, const RE2& re, A&&... a) { + return Apply(FindAndConsumeN, input, re, Arg(std::forward(a))...); + } +#endif // Replace the first match of "pattern" in "str" with "rewrite". // Within "rewrite", backslash-escaped digits (\1 to \9) can be @@ -436,12 +471,12 @@ class RE2 { // The map records the index of the leftmost group // with the given name. // Only valid until the re is deleted. - const map& NamedCapturingGroups() const; + const std::map& NamedCapturingGroups() const; // Return a map from capturing indices to names. // The map has no entries for unnamed groups. // Only valid until the re is deleted. - const map& CapturingGroupNames() const; + const std::map& CapturingGroupNames() const; // General matching routine. // Match against text starting at offset startpos @@ -464,8 +499,8 @@ class RE2 { // whether submatch i matched the empty string or did not match: // either way, match[i].data() == NULL. bool Match(const StringPiece& text, - int startpos, - int endpos, + size_t startpos, + size_t endpos, Anchor anchor, StringPiece *match, int nmatch) const; @@ -623,19 +658,7 @@ class RE2 { void set_one_line(bool b) { one_line_ = b; } void Copy(const Options& src) { - encoding_ = src.encoding_; - posix_syntax_ = src.posix_syntax_; - longest_match_ = src.longest_match_; - log_errors_ = src.log_errors_; - max_mem_ = src.max_mem_; - literal_ = src.literal_; - never_nl_ = src.never_nl_; - dot_nl_ = src.dot_nl_; - never_capture_ = src.never_capture_; - case_sensitive_ = src.case_sensitive_; - perl_classes_ = src.perl_classes_; - word_boundary_ = src.word_boundary_; - one_line_ = src.one_line_; + *this = src; } int ParseFlags() const; @@ -654,10 +677,6 @@ class RE2 { bool perl_classes_; bool word_boundary_; bool one_line_; - - //DISALLOW_COPY_AND_ASSIGN(Options); - Options(const Options&); - void operator=(const Options&); }; // Returns the options set in the constructor. @@ -670,10 +689,8 @@ class RE2 { static inline Arg CRadix(unsigned int* x); static inline Arg CRadix(long* x); static inline Arg CRadix(unsigned long* x); - #if RE2_HAVE_LONGLONG static inline Arg CRadix(long long* x); static inline Arg CRadix(unsigned long long* x); - #endif static inline Arg Hex(short* x); static inline Arg Hex(unsigned short* x); @@ -681,10 +698,8 @@ class RE2 { static inline Arg Hex(unsigned int* x); static inline Arg Hex(long* x); static inline Arg Hex(unsigned long* x); - #if RE2_HAVE_LONGLONG static inline Arg Hex(long long* x); static inline Arg Hex(unsigned long long* x); - #endif static inline Arg Octal(short* x); static inline Arg Octal(unsigned short* x); @@ -692,19 +707,17 @@ class RE2 { static inline Arg Octal(unsigned int* x); static inline Arg Octal(long* x); static inline Arg Octal(unsigned long* x); - #if RE2_HAVE_LONGLONG static inline Arg Octal(long long* x); static inline Arg Octal(unsigned long long* x); - #endif private: void Init(const StringPiece& pattern, const Options& options); bool DoMatch(const StringPiece& text, - Anchor anchor, - int* consumed, - const Arg* const args[], - int n) const; + Anchor anchor, + size_t* consumed, + const Arg* const args[], + int n) const; re2::Prog* ReverseProg() const; @@ -725,10 +738,10 @@ class RE2 { mutable int num_captures_; // Number of capturing groups // Map from capture names to indices - mutable const map* named_groups_; + mutable const std::map* named_groups_; // Map from capture indices to names - mutable const map* group_names_; + mutable const std::map* group_names_; // Onces for lazy computations. mutable std::once_flag rprog_once_; @@ -736,9 +749,8 @@ class RE2 { mutable std::once_flag named_groups_once_; mutable std::once_flag group_names_once_; - //DISALLOW_COPY_AND_ASSIGN(RE2); - RE2(const RE2&); - void operator=(const RE2&); + RE2(const RE2&) = delete; + RE2& operator=(const RE2&) = delete; }; /***** Implementation details *****/ @@ -749,7 +761,7 @@ class RE2 { template class _RE2_MatchObject { public: - static inline bool Parse(const char* str, int n, void* dest) { + static inline bool Parse(const char* str, size_t n, void* dest) { if (dest == NULL) return true; T* object = reinterpret_cast(dest); return object->ParseFrom(str, n); @@ -764,31 +776,29 @@ class RE2::Arg { // Constructor specially designed for NULL arguments Arg(void*); - typedef bool (*Parser)(const char* str, int n, void* dest); + typedef bool (*Parser)(const char* str, size_t n, void* dest); // Type-specific parsers -#define MAKE_PARSER(type,name) \ - Arg(type* p) : arg_(p), parser_(name) { } \ - Arg(type* p, Parser parser) : arg_(p), parser_(parser) { } \ - +#define MAKE_PARSER(type, name) \ + Arg(type* p) : arg_(p), parser_(name) {} \ + Arg(type* p, Parser parser) : arg_(p), parser_(parser) {} MAKE_PARSER(char, parse_char); - MAKE_PARSER(signed char, parse_char); + MAKE_PARSER(signed char, parse_schar); MAKE_PARSER(unsigned char, parse_uchar); + MAKE_PARSER(float, parse_float); + MAKE_PARSER(double, parse_double); + MAKE_PARSER(string, parse_string); + MAKE_PARSER(StringPiece, parse_stringpiece); + MAKE_PARSER(short, parse_short); MAKE_PARSER(unsigned short, parse_ushort); MAKE_PARSER(int, parse_int); MAKE_PARSER(unsigned int, parse_uint); MAKE_PARSER(long, parse_long); MAKE_PARSER(unsigned long, parse_ulong); - #if RE2_HAVE_LONGLONG MAKE_PARSER(long long, parse_longlong); MAKE_PARSER(unsigned long long, parse_ulonglong); - #endif - MAKE_PARSER(float, parse_float); - MAKE_PARSER(double, parse_double); - MAKE_PARSER(string, parse_string); - MAKE_PARSER(StringPiece, parse_stringpiece); #undef MAKE_PARSER @@ -799,29 +809,31 @@ class RE2::Arg { : arg_(p), parser_(parser) { } // Parse the data - bool Parse(const char* str, int n) const; + bool Parse(const char* str, size_t n) const; private: void* arg_; Parser parser_; - static bool parse_null (const char* str, int n, void* dest); - static bool parse_char (const char* str, int n, void* dest); - static bool parse_uchar (const char* str, int n, void* dest); - static bool parse_float (const char* str, int n, void* dest); - static bool parse_double (const char* str, int n, void* dest); - static bool parse_string (const char* str, int n, void* dest); - static bool parse_stringpiece (const char* str, int n, void* dest); - -#define DECLARE_INTEGER_PARSER(name) \ - private: \ - static bool parse_ ## name(const char* str, int n, void* dest); \ - static bool parse_ ## name ## _radix( \ - const char* str, int n, void* dest, int radix); \ - public: \ - static bool parse_ ## name ## _hex(const char* str, int n, void* dest); \ - static bool parse_ ## name ## _octal(const char* str, int n, void* dest); \ - static bool parse_ ## name ## _cradix(const char* str, int n, void* dest) + static bool parse_null (const char* str, size_t n, void* dest); + static bool parse_char (const char* str, size_t n, void* dest); + static bool parse_schar (const char* str, size_t n, void* dest); + static bool parse_uchar (const char* str, size_t n, void* dest); + static bool parse_float (const char* str, size_t n, void* dest); + static bool parse_double (const char* str, size_t n, void* dest); + static bool parse_string (const char* str, size_t n, void* dest); + static bool parse_stringpiece (const char* str, size_t n, void* dest); + +#define DECLARE_INTEGER_PARSER(name) \ + private: \ + static bool parse_##name(const char* str, size_t n, void* dest); \ + static bool parse_##name##_radix(const char* str, size_t n, void* dest, \ + int radix); \ + \ + public: \ + static bool parse_##name##_hex(const char* str, size_t n, void* dest); \ + static bool parse_##name##_octal(const char* str, size_t n, void* dest); \ + static bool parse_##name##_cradix(const char* str, size_t n, void* dest) DECLARE_INTEGER_PARSER(short); DECLARE_INTEGER_PARSER(ushort); @@ -829,29 +841,31 @@ class RE2::Arg { DECLARE_INTEGER_PARSER(uint); DECLARE_INTEGER_PARSER(long); DECLARE_INTEGER_PARSER(ulong); - #if RE2_HAVE_LONGLONG DECLARE_INTEGER_PARSER(longlong); DECLARE_INTEGER_PARSER(ulonglong); - #endif #undef DECLARE_INTEGER_PARSER + }; inline RE2::Arg::Arg() : arg_(NULL), parser_(parse_null) { } inline RE2::Arg::Arg(void* p) : arg_(p), parser_(parse_null) { } -inline bool RE2::Arg::Parse(const char* str, int n) const { +inline bool RE2::Arg::Parse(const char* str, size_t n) const { return (*parser_)(str, n, arg_); } // This part of the parser, appropriate only for ints, deals with bases -#define MAKE_INTEGER_PARSER(type, name) \ - inline RE2::Arg RE2::Hex(type* ptr) { \ - return RE2::Arg(ptr, RE2::Arg::parse_ ## name ## _hex); } \ - inline RE2::Arg RE2::Octal(type* ptr) { \ - return RE2::Arg(ptr, RE2::Arg::parse_ ## name ## _octal); } \ - inline RE2::Arg RE2::CRadix(type* ptr) { \ - return RE2::Arg(ptr, RE2::Arg::parse_ ## name ## _cradix); } +#define MAKE_INTEGER_PARSER(type, name) \ + inline RE2::Arg RE2::Hex(type* ptr) { \ + return RE2::Arg(ptr, RE2::Arg::parse_##name##_hex); \ + } \ + inline RE2::Arg RE2::Octal(type* ptr) { \ + return RE2::Arg(ptr, RE2::Arg::parse_##name##_octal); \ + } \ + inline RE2::Arg RE2::CRadix(type* ptr) { \ + return RE2::Arg(ptr, RE2::Arg::parse_##name##_cradix); \ + } MAKE_INTEGER_PARSER(short, short) MAKE_INTEGER_PARSER(unsigned short, ushort) @@ -859,15 +873,62 @@ MAKE_INTEGER_PARSER(int, int) MAKE_INTEGER_PARSER(unsigned int, uint) MAKE_INTEGER_PARSER(long, long) MAKE_INTEGER_PARSER(unsigned long, ulong) -#if RE2_HAVE_LONGLONG MAKE_INTEGER_PARSER(long long, longlong) MAKE_INTEGER_PARSER(unsigned long long, ulonglong) -#endif #undef MAKE_INTEGER_PARSER +#ifndef SWIG +// Helper for writing global or static RE2s safely. +// Write +// static LazyRE2 re = {".*"}; +// and then use *re instead of writing +// static RE2 re(".*"); +// The former is more careful about multithreaded +// situations than the latter. +// +// N.B. This class never deletes the RE2 object that +// it constructs: that's a feature, so that it can be used +// for global and function static variables. +class LazyRE2 { + private: + struct NoArg {}; + + public: + typedef RE2 element_type; // support std::pointer_traits + + // Constructor omitted to preserve braced initialization in C++98. + + // Pretend to be a pointer to Type (never NULL due to on-demand creation): + RE2& operator*() const { return *get(); } + RE2* operator->() const { return get(); } + + // Named accessor/initializer: + RE2* get() const { + std::call_once(once_, [this]() { LazyRE2::Init(this); }); + return ptr_; + } + + // All data fields must be public to support {"foo"} initialization. + const char* pattern_; + RE2::CannedOptions options_; + NoArg barrier_against_excess_initializers_; + + mutable RE2* ptr_; + mutable std::once_flag once_; + + private: + static void Init(const LazyRE2* lazy_re2) { + lazy_re2->ptr_ = new RE2(lazy_re2->pattern_, lazy_re2->options_); + } + + void operator=(const LazyRE2&); // disallowed +}; +#endif // SWIG + } // namespace re2 using re2::RE2; +using re2::LazyRE2; -#endif /* RE2_RE2_H */ +#endif // RE2_RE2_H_ diff --git a/ci/after_success.sh b/ci/after_success.sh new file mode 100755 index 0000000000..2cf60f16e5 --- /dev/null +++ b/ci/after_success.sh @@ -0,0 +1,34 @@ +#!/bin/bash + +# This runs only when a commit is pushed to master. It is responsible for +# updating docs and computing coverage statistics. + +set -e + +if [ "$TRAVIS_RUST_VERSION" != "nightly" ] || [ "$TRAVIS_PULL_REQUEST" != "false" ] || [ "$TRAVIS_BRANCH" != "master" ]; then + exit 0 +fi + +env + +# Build and upload docs. +echo '' > target/doc/index.html +ve=$(mktemp -d) +virtualenv "$ve" +"$ve"/bin/pip install --upgrade pip +"$ve"/bin/pip install ghp-import +"$ve"/bin/ghp-import -n target/doc +git push -qf https://${TOKEN}@github.com/${TRAVIS_REPO_SLUG}.git gh-pages + +# Install kcov. +tmp=$(mktemp -d) +pushd "$tmp" +wget https://github.com/SimonKagstrom/kcov/archive/master.tar.gz +tar zxf master.tar.gz +mkdir kcov-master/build +cd kcov-master/build +cmake .. +make +make install DESTDIR="$tmp" +popd +PATH="$tmp/usr/local/bin:$PATH" ./ci/run-kcov --coveralls-id $TRAVIS_JOB_ID diff --git a/run-kcov b/ci/run-kcov similarity index 95% rename from run-kcov rename to ci/run-kcov index 6f977d213b..91fb17163f 100755 --- a/run-kcov +++ b/ci/run-kcov @@ -12,7 +12,6 @@ tests=( nfa_utf8bytes nfa_bytes regex - regex_inline ) tmpdir=$(mktemp -d) with_plugin= @@ -43,7 +42,7 @@ if [ -n "$with_plugin" ]; then $(ls -t ./regex_macros/target/debug/plugin-* | head -n1) fi -cargo test --no-run --verbose +cargo test --no-run --verbose --jobs 4 for t in ${tests[@]}; do kcov \ --verify \ diff --git a/run-shootout-test b/ci/run-shootout-test similarity index 100% rename from run-shootout-test rename to ci/run-shootout-test diff --git a/ci/script.sh b/ci/script.sh new file mode 100755 index 0000000000..11ebc904ae --- /dev/null +++ b/ci/script.sh @@ -0,0 +1,35 @@ +#!/bin/sh + +# This is the main CI script for testing the regex crate and its sub-crates. + +set -e + +# Builds the regex crate and runs tests. +cargo build --verbose +cargo doc --verbose +if [ "$TRAVIS_RUST_VERSION" = "nightly" ]; then + cargo build --verbose --manifest-path regex-debug/Cargo.toml + RUSTFLAGS="-C target-feature=+ssse3" cargo test --verbose --features 'simd-accel pattern' --jobs 4 +else + cargo test --verbose --jobs 4 +fi + +# Run a test that confirms the shootout benchmarks are correct. +ci/run-shootout-test + +# Run tests on regex-syntax crate. +cargo test --verbose --manifest-path regex-syntax/Cargo.toml +cargo doc --verbose --manifest-path regex-syntax/Cargo.toml + +# Run tests on regex-capi crate. +cargo build --verbose --manifest-path regex-capi/Cargo.toml +(cd regex-capi/ctest && ./compile && LD_LIBRARY_PATH=../target/debug ./test) +(cd regex-capi/examples && ./compile && LD_LIBRARY_PATH=../target/release ./iter) + +# Make sure benchmarks compile. Don't run them though because they take a +# very long time. +if [ "$TRAVIS_RUST_VERSION" = "nightly" ]; then + for x in rust rust-bytes pcre1 onig; do + (cd bench && ./run $x --no-run) + done +fi diff --git a/regex-syntax/Cargo.toml b/regex-syntax/Cargo.toml index c386b48a75..0a79df7abf 100644 --- a/regex-syntax/Cargo.toml +++ b/regex-syntax/Cargo.toml @@ -9,5 +9,5 @@ homepage = "https://github.com/rust-lang/regex" description = "A regular expression parser." [dev-dependencies] -quickcheck = "0.4.1" +quickcheck = { version = "0.4.1", default-features = false } rand = "0.3.15"