/src/Editing/Tests.hs
http://github.com/Eelis/geordi · Haskell · 464 lines · 409 code · 23 blank · 32 comment · 17 complexity · 3e418083181f2f751a6c7f5277af3a7b MD5 · raw file
- {-# LANGUAGE UnicodeSyntax #-}
- module Main (main) where
- import qualified Editing.EditsPreparation
- import qualified Editing.Parse
- import qualified Editing.Execute
- import qualified Editing.Diff
- import qualified Cxx.Show
- import qualified Cxx.Parse
- import Parsers (eof, parseOrFailE)
- import Util (test_cmp, (<<), (.))
- import Request (EditableRequest(..), EditableRequestKind(..))
- import Prelude hiding ((.))
- import Data.SetOps
- basic_tests :: IO ()
- basic_tests = do
- f "" "make foo bar bas" "Unexpected end of command. Expected \"::\" or template-arguments."
- f "" "make " "Unexpected end of command. Expected \"declaration\", \"body\", production-name, \"all\", \"any\", \"every\", \"each\", ordinal, or declarator-id."
- f "" "make i pointer to" "Unexpected end of command. Expected type description."
- s "mutable int i;" "make i const" "const mutable int i;"
- s "int i;" "make i a const double" "double const i;"
- s "int const i;" "make i a double" "double const i;"
- s "void g(int); void f() { bind(&g)(3, 2); }" "make g a function taking two integers" "void g(int, int); void f() { bind(&g)(3, 2); }"
- -- "bind(&g)(3, 2);" is determined not to be declaration because it would be a reference initialized with two arguments.
- s "int i;" "make i a *&" "int *& i;"
- s "int * p = f();" "make p auto" "auto p = f();"
- s "inline void f();" "make f noninline" "void f();"
- s "int (* const i)(double);" "make i nonconst" "int (* i)(double);"
- s "int i;" "make i a pointer&" "int *& i;"
- f "int i;" "make j const" "Could not find free declaration of j."
- s "void f() { int i; i; i = 0; }" "make i a pointer" "void f() { int * i; i; i = 0; }"
- s "struct X { static void f(); }" "append semicolon and make f pure" "struct X { virtual void f()= 0 ; };"
- s "struct X { virtual void f() = 0; };" "make f static" "struct X { static void f() ; };"
- s "struct X { void f(); };" "make f virtual pure const inline explicit" "struct X { virtual inline explicit void f()const = 0 ; };"
- s "struct X { ~X(); };" "make ~ X virtual" "struct X { virtual ~X(); };"
- s "struct X { virtual inline explicit void f()const = 0 ; };" "make f impure nonvirtual nonexplicit noninline" "struct X { void f()const ; };"
- s "struct X { X(int i); };" "make i a reference to const and make constructor explicit" "struct X { explicit X(const int & i); };"
- s "int *p;" "make p a const*volatile" "const int *volatile p;"
- s "void N::f() {}" "make N::f inline" "inline void N::f() {}"
- s "struct X { void operator++(); };" "make operator++ a const function returning an X&" "struct X { X & operator++()const ; };"
- s "int x /*haha*/ ; // ok dan /* mja */" "make x const" "const int x /*haha*/ ; // ok dan /* mja */"
- s "T const ( &f() )[3] { T x = {v}; }" "make f inline" "inline T const ( &f() )[3] { T x = {v}; }"
- s "int *i; int * & j;" "make i a pointer to a pointer" "int ** i; int * & j;"
- s "struct Factorial { static int v = N; };" "make v const" "struct Factorial { const static int v = N; };"
- s "{ struct S {}; int (S:: * p) = 0; int (S:: * & r) = p; }" "make p and r const" "{ struct S {}; int (S:: * const p) = 0; int (S:: * const & r) = p; }"
- s "int i;" "make i an array" "int i[];"
- s "void f() { try { int long i; } catch(int long j) {} }" "make i and j long long" "void f() { try { long long int i; } catch(long long int j) {} }"
- s "void f() { try { long long i; } catch(long long j) {} }" "make i and j long" "void f() { try { long i; } catch(long j) {} }"
- s "int i;" "make i a const array" "const int i[];"
- s "int i;" "make i a const array of pointers" "int *const i[];"
- s "int i[];" "make i const" "const int i[];"
- s "struct X { ~X(); }" "append ; and make destructor virtual and show" "struct X { virtual ~X(); };"
- s "{ try{}catch(const int i){} }" "make i volatile" "{ try{}catch(volatile const int i){} }"
- s "void f(int i, double d){}" "make i and d long" "void f(long int i, long double d){}"
- s "void f(int i, int j, int k);" "make second parameter-declaration const and erase third parameter-declaration" "void f(int i, const int j);"
- s "void f(float, int, char, double);" "make second and third parameter-declaration const" "void f(float, const int, const char, double);"
- s "{ if(int i = 3) ; }" "make i const" "{ if(const int i = 3) ; }"
- s "int i;" "make i an array of const" "const int i[];"
- s "int i;" "make i a static const function" "static int i()const ;"
- s "int i;" "make i a pointer to a function" "int (* i)();"
- s "int i;" "make i a pointer to a function taking two doubles" "int (* i)(double, double);"
- s "int i;" "make i a function returning a const" "const int i();"
- s "int i;" "make i a function returning a const pointer and taking a bool" "int *const i(bool);"
- s "{ cout << 3, 3.2, 3ul, 3e+2, 0x3, 03, .3, 3., .3e1, 3.E0; int i; }" "make i const" "{ cout << 3, 3.2, 3ul, 3e+2, 0x3, 03, .3, 3., .3e1, 3.E0; const int i; }"
- s "void f(int i) { try {} catch(int j) {} }" "make f and i and j const" "void f(const int i) const { try {} catch(const int j) {} }"
- f "void f(int i) { try {} catch(int j) {} }" "make j mutable" "Invalid decl-specifier for type-specifier-seq: mutable"
- s "struct X { void f(int p); };" "make f static inline and make p a reference to long" "struct X { static inline void f(long int & p); };"
- s "struct X { operator ()(); };" "make operator() const" "struct X { operator ()()const ; };" -- Spaces don't matter when matching declarator-ids.
- s "<< 3, i; int i = 2;" "make i const" "<< 3, i; const int i = 2;"
- putStrLn "All make tests passed."
- t "erase all 2 and insert x before second 3 and prepend y" $ Right "y1 3 x3 4 5"
- t "erase everything before last 2 and replace everything after 4 with x" $ Right "2 3 4x"
- t "insert x after all 2 and append y" $ Right "1 2x 3 2x 3 4 5y"
- t "erase first 2 and replace second 2 with x and omit last " $ Right "1 3 x 3 45"
- t "erase first and last 2 and all 3 and 4 and everything before first 2 and everything after 4" $ Right " "
- t "erase third last space and kill everything after second last " $ Right "1 2 3 23 "
- t "insert x after 1 2 and before all 3 and erase 5 and prepend y" $ Right "y1 2x x3 2 x3 4 "
- t "erase everything before 4 and everything after 5" $ Right "4 5"
- t "insert x before 3 4 and 5" $ Right "1 2 3 2 x3 4 x5"
- t "insert x after 1 and all 3 and before 5 and erase 4" $ Right "1x 2 3x 2 3x x5"
- t "erase second space before 4" $ Right "1 2 3 23 4 5"
- t "erase first 2 3 and 3 2 and 4 5 and last " $ Right "1 3 "
- t "move 1 till second 3 to before 5" $ Right "3 4 1 2 3 2 5"
- t "move 1 till after second 3 to before 5" $ Right " 4 1 2 3 2 35"
- t "swap last 2 3 and last space before 4" $ Right "1 2 3 2 34 5"
- t "swap last 2 3 with last space before 4" $ Right "1 2 3 2 34 5"
- t "swap 1 and first 3 and second 3 and 5" $ Right "3 2 1 2 5 4 3"
- t "replace 2 after second space with x" $ Right "1 2 3 x 3 4 5"
- t "move everything till 4 to end and erase 4 " $ Right "51 2 3 2 3 "
- t "erase everything" $ Right ""
- t "insert x after second space before 4" $ Right "1 2 3 2 x3 4 5"
- t "add < and > around second 3" $ Right "1 2 3 2 <3> 4 5"
- t "add braces around everything" $ Right "{1 2 3 2 3 4 5}"
- t "move everything after second 3 to begin" $ Right " 4 51 2 3 2 3"
- t "move second 3 to end and 5 to begin" $ Right "51 2 3 2 4 3"
- t "erase first space until second space before 4" $ Right "1 3 4 5"
- t "erase spaces" $ return "1232345"
- t "erase second last space before 4" $ Right "1 2 3 23 4 5"
- t "erase after second 2" $ Right "1 2 3 2"
- t "erase after second 2 until before 5" $ Right "1 2 3 25"
- t "erase 1 and erase 1" $ Right " 2 3 2 3 4 5"
- t "erase before second last space" $ Right " 4 5"
- t "move 4 5 to before 1 and erase everything after second 2" $ Right "4 51 2 3 2"
- t "erase everything between last and first 2" $ Right "1 22 3 4 5"
- t "erase everything between second 2 and begin" $ Right "2 3 4 5"
- t "erase all space between second 2 and 4" $ Right "1 2 3 234 5"
- t "erase from first 3 until after everything" $ Right "1 2 "
- t "erase 2 after and before first 3" $ return "1 3 3 4 5"
- t "add + before and after 4" $ return "1 2 3 2 3 +4+ 5"
- t "move before second 3 until 4 to begin" $ Right "3 1 2 3 2 4 5"
- t "erase everything between begin and end" $ Right ""
- t "move everything between first 3 and 4 to begin" $ Right " 2 3 1 2 34 5"
- t "erase before second 3 until 4" $ Right "1 2 3 2 4 5"
- t "insert x before second 3 and at end" $ Right "1 2 3 2 x3 4 5x"
- t "erase until after second 3" $ Right " 4 5"
- t "erase from before second 3" $ Right "1 2 3 2 "
- t "replace all but first and second last space with x" $ Right "1 2x3x2x3 4x5"
- t "change all but first and second last space to x" $ Right "1 2x3x2x3 4x5"
- t "erase between second and fourth space and 1" $ Right " 2 3 4 5"
- t "erase between the first and third space and prepend x" $ Right "x1 2 3 4 5"
- t "add parentheses around every space between first 2 and 4 and around 5 and erase second last 3" $ Right "1 2( )( )2( )3( )4 (5)"
- t "move from first 3 until 4 to begin" $ Right "3 2 3 41 2 5"
- t "erase everything from before everything until the second 3" $ Right "3 4 5"
- t "add parentheses around first 2 and 5" $ Right "1 (2) 3 2 3 4 (5)"
- t "erase everything between first space and last space" $ Right "1 5"
- t "erase all 3 and all 2 between begin and end" $ Right "1 4 5"
- t "erase everything between second and first 2 " $ Right "1 2 2 3 4 5"
- t "erase from second 2 till last space" $ Right "1 2 3 5"
- t "erase from second 2 until after 3 and add x before 4" $ Right "1 2 3 x4 5"
- -- t "erase everything between 1 and the second 2 and everything between 4 and 5" $ Right "12 3 45"
- t "erase from before 4 until end" $ Right "1 2 3 2 3 "
- t "use 5x and y4" $ Right "1 2 3 2 3 y4 5x"
- t "erase everything from after 1 until second last space" $ Right "1 4 5"
- t "add parentheses around everything between 1 and second space before 4" $ Right "1( 2 3 2) 3 4 5"
- t "add + and - around all 3 and second 2 and prepend x" $ Right "x1 2 +3- +2- +3- 4 5"
- t "move 4 till end to front" $ Right "4 51 2 3 2 3 "
- t "erase all space after first 2" $ Right "1 232345"
- t "add x before first 3 after second 2" $ Right "1 2 3 2 x3 4 5"
- t "add x before second space after second 3" $ Right "1 2 3 2 3 4x 5"
- t "add x after all space before first 3" $ Right "1 x2 x3 2 3 4 5"
- t "erase all space before last 3" $ Right "12323 4 5"
- t "erase second 2 till end" $ Right "1 2 3 "
- t "append x before 5 and prepend y before all 2 between first 3 and 5" $ Right "1 2 3 y2 3 4 x5"
- t "move everything after second 3 to begin" $ Right " 4 51 2 3 2 3"
- t "replace first 2 with x and replace all 2 with x" $ Right "1 x 3 x 3 4 5"
- t "erase everything until 4 and 5" $ Right "4 "
- t "erase 3 2 till 5" $ Right "1 2 5"
- t "move second 2 to back and prepend x" $ Right "x1 2 3 3 4 52"
- t "cut everything before first 2 and first and second 3 and everything after 4 and prepend x" $ Right "x2 2 4"
- t "replace all 2 with 3 and erase all 3 and add x after second 2" $ Right "1 3 3x 4 5"
- t "insert spacer before 4 and insert a semicolon after 1 and erase last space" $ Right "1; 2 3 2 3 spacer45"
- t "erase first and second last " $ Right "12 3 2 34 5"
- t "replace 1 with x and all 2 with y and erase second 3" $ Right "x y 3 y 4 5"
- t "move everything after last 3 to front and erase 5" $ Right " 4 1 2 3 2 3"
- t "erase spaces around first 2" $ Right "123 2 3 4 5"
- t "erase spaces around 3 after second 2" $ Right "1 2 3 234 5"
- t "erase 1 and 2 around first space" $ Right " 3 2 3 4 5"
- t "erase all but first two spaces" $ Right "1 2 32345"
- t "add x after 4 and add y after 4" $ Right "1 2 3 2 3 4yx 5"
- t "erase 4 and add y before 4 and add x after 4" $ Right "1 2 3 2 3 yx 5"
- t "move 4 to end and insert x before 5" $ Right "1 2 3 2 3 x54"
- t "erase 4 and move 5 to begin" $ Right "51 2 3 2 3 "
- t "move 3 2 3 to front and insert x before second 2" $ Right "3 x2 31 2 4 5"
- t "append float x; int y;" $ Right "1 2 3 2 3 4 5float x; int y;"
- t "erase 5 and move everything after last 3 to front" $ Right " 4 1 2 3 2 3"
- t "move everything before 4 to end and move first 3 to front" $ Right "34 51 2 2 3 "
- t "move 3 4 5 to before 4" $ Left "Move destination lies in source range."
- t "move 1 and 4 to after first 3" $ Right " 2 314 2 3 5"
- -- Order-sensitive edits:
- t "add parentheses around everything and append x" $ Right "(1 2 3 2 3 4 5)x"
- t "add parentheses around all 3 and all 2 and erase 4" $ Right "1 (2) (3) (2) (3) 5"
- t "append x and add parentheses around everything" $ Right "(1 2 3 2 3 4 5x)"
- t "append x after everything before 4 and add y before 4" $ Right "1 2 3 2 3 xy4 5"
- t "insert y before 4 and insert z after second 3 " $ Right "1 2 3 2 3 zy4 5"
- t "prepend x and move 5 to begin and insert y before 1 and insert z before everything" $ Right "z5xy1 2 3 2 3 4 "
- t "add parentheses around everything and prepend x" $ Right "x(1 2 3 2 3 4 5)"
- t "prepend x and add parentheses around everything" $ Right "(x1 2 3 2 3 4 5)"
- t "prepend x before everything after 4 and add y after 4" $ Right "1 2 3 2 3 4yx 5"
- t "add y after 4 and prepend x before everything after 4" $ Right "1 2 3 2 3 4xy 5"
- -- Semantic edits:
- ct "a x;" "add b after first identifier" $ Right "ab x;"
- ct "struct X { operator bool() { return true; } };" "move declaration of operator bool to end" $ Right "struct X { };operator bool() { return true; } "
- ct "namespace N { void f(); } class C { void g() {} };" "swap body of N and body of C" $ Right "namespace N { void g() {} } class C { void f(); };"
- ct "void f() { int i; } void g() { int j; } void h() {}" "prepend BARK; in f and append BARK; in g and in h" $ Right "void f() { BARK;int i; } void g() { int j; BARK;} void h() {BARK;}"
- ct "class C { int f() {} };" "add int x; in C and add return x; in f" $ Right "class C { int f() {return x;} int x;};"
- ct "void f() { cout << 3; g(); }" "erase everything from after 3; until after body of f" $ Right "void f() { cout << 3;}"
- ct "int main() { cout << 3; }" "move << 3 to front and erase declaration of main" $ Right "<< 3"
- ct "{ cout << x; } enum E { x };" "add `cout, y;` in main and add ,y in E" $ Right "{ cout << x; cout, y;} enum E { x ,y};"
- ct "namespace N { void f(); void g(); void f(); } void h();" "add int x; after declaration of g in N" $ Right "namespace N { void f(); void g();int x; void f(); } void h();"
- ct "struct X { void f(); }; struct Y { void f(); };" "erase declaration of f in Y" $ Right "struct X { void f(); }; struct Y { };"
- ct "namespace N { void f(); void g(); void f(); } void h();" "move declaration of h to after declaration of g in N" $ Right "namespace N { void f(); void g(); void h();void f(); } "
- ct "void f() {} void g() {} namespace N { void f() {} } void f(int) {}" "add int x; in f in N and in g and append y" $ Right "void f() {} void g() {int x;} namespace N { void f() {int x;} } void f(int) {}y"
- ct "void f() { int x; } void g() { int x; } void h() { int x; }" "erase declaration of x in f and h" $ Right "void f() { } void g() { int x; } void h() { }"
- ct "namespace N { int x; } int x; void f() { int x; }" "use int y; in N and f" $ Right "namespace N { int y; } int x; void f() { int y; }"
- ct "void f() {} void f(int) {} void f(double) {} void f(char) {}" "add int x; in first f and in third and fourth body of f" $ Right "void f() {int x;} void f(int) {} void f(double) {int x;} void f(char) {int x;}"
- ct "namespace A { int x; namespace B { int x; namespace C { int x; namespace D { int x; } } } }" "erase declaration of x in D in C in B in A" $ Right "namespace A { int x; namespace B { int x; namespace C { int x; namespace D { } } } }"
- ct "struct X { X(int); };" "erase second declaration of X" $ Right "struct X { };"
- ct "template <typename> void f(); void f(int);" "erase second declaration of f" $ Right "template <typename> void f(); "
- ct "struct X { template <typename U> X(U); };" "erase second declaration of X" $ Right "struct X { };"
- ct "struct X { int x; X(); void f(); ~X(); struct Y {}; operator int(); X(int); };" "erase constructors and replace destructor with int y;" $ Right "struct X { int x; void f(); int y; struct Y {}; operator int(); };"
- ct "template <typename T> struct X { template <typename U> inline X(T, U); ~X(); }; template <typename T> template <typename U> X<T>::X(T, U) {} template<typename T> X<T>::~X() {}" "erase second constructor and second destructor" $ Right "template <typename T> struct X { template <typename U> inline X(T, U); ~X(); }; "
- ct "void f(int i);" "erase declaration of i" $ Right "void f();"
- ct "struct X { int i; };" "erase declaration of i" $ Right "struct X { };"
- ct "{ 3; 4; 5; }" "swap first and last statement" $ Right "{ 5; 4; 3; }"
- ct "{ 3; 4; 5; }" "swap statements around 4;" $ Right "{ 5; 4; 3; }"
- ct "{ 3; 4; 5; 6; }" "swap statements before 5 with last statement" $ Right "{ 6; 5; 3; 4; }"
- ct "void f(int,double,char);" "swap first two parameter-declarations" $ return "void f(double,int,char);"
- --todo: ct "{ if(b) 3; 4; 5; }" "add curlies around first two statements after if" $ Right "{ if(b) {3; 4;} 5; }"
- --todo: ct "{ 3; 4; 5; }" "add curlies around first and second statement" $ Right "{ {3; 4;} 5; }"
- ct "{ 3; 4; 5; }" "add curlies around first statement and around second statement" $ Right "{ {3;} {4;} 5; }"
- ct "<< max(3, 2, 1)" "add curlies around code between parens" $ return "<< max({3, 2, 1})"
- ct "{ 1;2;3;4;5; }" "swap first two statements with last two statements" $ Right "{ 4;5; 3;1;2;}"
- ct "{ 1;2;3; }" "swap first two statements" $ Right "{ 2;1;3; }"
- --ct "void f() { 1; } void g() { 1; 2; 3; 4; }" "replace first two and last statement in g with 0;" $ Right "void f() { 1; } void g() { 0;3; 0;}"
- ct "void f() { int x = 3; cout << x; } int i;" "replace everything after first statement in f with BARK;" $ Right "void f() { int x = 3; BARK;} int i;"
- ct "template <typename T, int i> struct S;" "erase second template-parameter" $ return "template <typename T> struct S;"
- ct "void g(string s); void f(int i, double d, char c, float, bool b);" "erase first and last two parameter-declarations in declaration of f and replace third parameter-declaration in declaration of f with wchar_t c" $ return "void g(string s); void f(double d, wchar_t c);"
- ct "int f();" "replace type-specifier with void" $ Right "void f();"
- ct "void g() { 0; struct X { void f() { 1;2;3;4; } }; 1; }" "erase statements around 2 in f" $ Right "void g() { 0; struct X { void f() { 2;} }; 1; }"
- ct "int a;in@@@t x;int y;int z;" "erase @@@ and erase int a; and erase second declaration" $ Right "int y;int z;"
- ct "@ int x;" "erase @ and replace declaration of x by bla" $ return " bla"
- ct "@@@@@ void f(){} int x;" "erase @@@@@ and erase first x after function-definition" $ Right " void f(){} int ;"
- ct "@@@@int x; int y; int z;" "erase @@@@ and erase from start until second declaration" $ Right "int z;"
- ct "@@@@int x; int y; int z;" "erase @@@@ and erase from second declaration until last space" $ Right "int x; z;"
- ct "class X extends Y { int i:2; };" "replace extends with : and replace literal after : with 3" $ Right "class X : Y { int i:3; };"
- ct "T f() { 0;x; } U y;" "erase everything after 0 in f" $ Right "T f() { 0} U y;"
- ct "T f() { 0;x; } U y;" "erase everything before x in f" $ Right "T f() { x; } U y;"
- ct "T f() { 0;1;2;3;4; } U y;" "erase everything between second and fourth statement in f" $ Right "T f() { 0;1;3;4; } U y;"
- ct "; void g() {} void f() { {1;} }" "erase first semicolon and erase curlies around 1;" $ return " void g() {} void f() { 1; }"
- -- Edit errors:
- ct "struct X { void f() { cout << 3; int x; cout << 3; } };" "erase second 3 after declaration of x in f in X" $ Left "String `3` does not occur twice after free declaration of x in f in X."
- t "erase second 4 after 1" $ Left "String `4` does not occur twice after 1."
- t "move second 2 to x" $ Left "Unexpected `x` after `second 2 to `. Expected \"beginning\", \"begin\", \"front\", \"start\", \"end\", \"back\", \"before\", or \"after\"."
- t "replace alligators with chickens" $ Left "String `alligators` does not occur."
- t "use banana" $ Left "No non-exact match for banana."
- t "use 5426" $ Left "No non-exact match for 5426."
- t "erase 2" $ Left "String `2` occurs multiple times."
- t "replace 1 and erase with 4" $ Left "String `erase` does not occur."
- t "replace tenth last 2 by x" $ Left "String `2` does not occur 10 times."
- t "erase second 9" $ Left "String `9` does not occur."
- t "replace all 2 with 3 and replace second 2 with x" $ Left "Overlapping edits: replace 2 with 3 and replace 2 with x."
- t "erase everything before first 3 and replace first 2 with x" $ Left "Overlapping edits: erase `1 2 ` and replace 2 with x."
- t "erase 5 between 1 and 4" $ Left "String `5` does not occur between 1 and 4."
- t "prepend x and replace 4 with a and replace 4 with b" $ Left "Overlapping edits: replace 4 with a and replace 4 with b."
- -- Syntax errors:
- t "isnert 3 before 4" $ Left "Unexpected `isnert` at start. Expected edit command."
- t "insert " $ Left "Unexpected end of command. Expected option, wrapping description, or verbatim string."
- t "insert kung fu" $ Left "Unexpected end of command. Expected \" and\", \" in\", \" at\", \" around\", \" before\", or \" after\"."
- t "move " $ Left "Unexpected end of command. Expected \"till\", \"until\", \"from\", \"everything\", \"code\", \"before\", \"between\", \"after\", \"declaration\", \"body\", production-name, verbatim string, \"all\", \"any\", \"every\", \"each\", or ordinal."
- t "move x " $ Left "Unexpected end of command. Expected \" till\", \" until\", \" around\", \" before\", \" after\", \" between\", \" in\", \" and\", or \" to\"."
- t "move x to "$ Left "Unexpected end of command. Expected \"beginning\", \"begin\", \"front\", \"start\", \"end\", \"back\", \"before\", or \"after\"."
- t "erase all 2 and " $ Left "Unexpected end of command. Expected verbatim string, \"till\", \"until\", \"from\", \"everything\", \"code\", \"before\", \"between\", \"after\", \"declaration\", \"body\", production-name, \"all\", \"any\", \"every\", \"each\", ordinal, wrapping description, option, or edit command."
- putStrLn "All basics tests passed."
- where
- ct :: String → String → Either String String → IO ()
- ct x c o = test_cmp c o $ case parseOrFailE (Editing.Parse.commandsP << eof) c "command" of
- Left e → Left e
- Right (cmds, _) → editable_body . Editing.Execute.execute Nothing cmds (EditableRequest (Evaluate (∅)) x)
- s, f :: String → String → String → IO ()
- s code cmdstring expectation = ct code cmdstring (Right expectation) -- test for success
- f code cmdstring expectation = ct code cmdstring (Left expectation) -- test for failure
- t = ct "1 2 3 2 3 4 5"
- diff_tests :: IO ()
- diff_tests = do
- dt' "foo; bar; monkey; chicken; bas;" "bar; monkey; chicken;" "Erased `foo;` and `bas;`." "Prepended `foo;` and appended `bas;`."
- dt' "{ fstream f(\"t.cpp\"); string s(istreambuf_iterator<char>(f), istreambuf_iterator<char>()); }"
- "{ fstream f(\"t.cpp\"); string s((istreambuf_iterator<char>(f)), istreambuf_iterator<char>()); }"
- "Inserted ( before `istreambuf_iterator<char>`, and inserted ) after `istreambuf_iterator<char>(f)`."
- "Erased ( before `istreambuf_iterator<char>` and ) after `istreambuf_iterator<char>(f)`."
- -- Todo: One day, the former should say "wrapped ...".
- dt' "int f(int & i) { i = 4; return i;} int g(int && i){return f(i);} int main() { cout << g(2); }"
- "int & f(int & i) { i = 4; return i;} int & g(int && i){return f(i);} int & g(int & i){return f(i);} int main() { cout << g(2); }"
- "Replaced `int f` with `int & f`, replaced `int g` with `int & g`, and inserted `int & g(int & i){return f(i);}` before `int main`."
- "Replaced `int & f` with `int f`, replaced `int & g` with `int g`, and erased `int & g(int & i){return f(i);}`."
- dt' "{string foo = \"kangaroo\"; auto m = foo.find_first_of('m'); cout << *m;}"
- "{string foo = \"kangaroo\"; size_t m = foo.find_first_of('m'); cout << foo[m];}"
- "Replaced `auto m` with `size_t m`, and replaced `<< *m` with `<< foo[m]`."
- "Replaced `size_t m` with `auto m`, and replaced `<< foo[m]` with `<< *m`."
- -- Todo: Group.
- dt "{int i=0,t=time(0);for(;i<5000000;i++)asm(\".org 0xffff\");cout << time(0)-t; }"
- "{int i=0,t=time(0);for(;i<5000;i++)int tmp=1*88+71/4000^66;cout << time(8)-t; }"
- "Replaced i<5000000 with i<5000, replaced `asm(\".org 0xffff\")` with `int tmp=1*88+71/4000^66`, and replaced 0 with 8."
- dt' "struct curr_func { string name; cf(string n):name(n){} }; \\ #define DEFUN(name) name try { throw curr_func(#name); } catch(curr_func& cfun) \\ DEFUN(void haha(int a)) { cout << cfun.name; } int main() { cout << haha; }"
- "struct curr_func { string name; curr_func(string n):name(n){} }; \\ #define DEFUN(name) name try { throw curr_func(#name); } catch(curr_func& cfun) \\ DEFUN(void haha(int a)) { cout << cfun.name << \": \" << a; } int main() { haha(42); }"
- "Replaced cf with curr_func, inserted `<< \": \" << a` after `<< cfun.name`, and replaced `cout << haha` with haha(42)."
- "Replaced curr_func with cf, erased `<< \": \" << a`, and replaced haha(42) with `cout << haha`."
- dt "{float i=0,t=time(0);for(;i<5000000;i++) { if(x == 3) f(reinterpret_cast<long>(x)); } }"
- "{int i=0,t=time(null);for(;i<5000000;++i) { if(x != 3) f(static_cast<long>(x)); } }"
- "Replaced `float i` with `int i`, replaced 0 with null, replaced i++ with ++i, replaced `x == 3` with `x != 3`, and replaced `reinterpret_cast<long>` with `static_cast<long>`."
- {-
- dt' "struct a { int b; a():b([]{ return 1 + 2 + 3; }){}}a_; int main() { cout << a_.b }"
- "struct a { int b; a({}):b([]{ return 1 + 2 + 3; }()){}}a_; int main() { cout << a_.b; }"
- "Replaced \"a():b([]{\" with \"a({}):b([]{\", replaced \")\" after \"return 1 + 2 + 3; }\" with \"())\", and inserted \";\" after \"cout << a_.b\"."
- "Replaced \"a({}):b([]{\" with \"a():b([]{\", replaced \"}()){}}a_\" with \"}){}}a_\", and erased \";\" after \"cout << a_.b\"."
- -}
- dt "struct curr_func { string name; cf(string n):name(n){} }; \\ #define DEFUN(name) name try { throw curr_func(#name); } catch(curr_func& cfun) \\ DEFUN(void haha(int a)) { cout << cfun.name; } int main() { cout << haha; }"
- "struct { string name; cf(string n){} }; \\ #define DEFUN(name) name try { } catch(curr_func& cfun) \\ DEFUN(void haha(int a) { cout << \"tortoise\"; } ) { cout << ETYPE(cfun.name); } int main() { do_something(complicated); cout << haha; }"
- "Replaced `struct curr_func` with struct, erased :name(n) and `throw curr_func(#name);`, inserted `{ cout << \"tortoise\"; }` before `) { cout`, replaced `<< cfun.name` with `<< ETYPE(cfun.name)`, and inserted `do_something(complicated);` before `cout << haha`."
- {-
- dt "{ char str[] = \"giraffe\"; char * pch; pch=(char*) memchr(str, 'y', (int)strlen(str)); if (pch!=NULL) { printf(\"'y' was found at position #%d\", pch-str+1); } }"
- "{ char * str = \"giraffe\"; char * pch; pch=(char*) memchr(str, 'v', (size_t)strlen(str)); if (pch!=NULL) { printf(\"'v' was found at position #%d\", pch-str-1); memset(str, '*', 6); puts(str); printf(\"%s\", str); } }"
- "Replaced `char str[]` with `char * str`, replaced 'y' with 'v', replaced int with size_t, replaced `\"'y' was` with `\"'v' was`, and replaced pch-str+1 with `pch-str-1); memset(str, '*', 6); puts(str); printf(\"%s\", str`."
- -}
- dt "geordi: { char y(34); stringstream i(\"geordi: { char y(34); stringstream i(!); string t; getline(i, t, '!'); cout << t << y << i.str() << y << i.rdbuf(); }\"); string t; getline(i, t, '!'); cout<< t << y << i.str() << y << i.rdbuf(); }"
- "geordi: { stringstream i(\"geordi: { stringstream i(!); string t; getline(i, t, '!'); cout << t << i.str() << i.rdbuf(); }\"); string t; getline(i, t, '!'); cout << t << i.str() << i.rdbuf(); }"
- "Erased `char y(34);` and `char y(34);` and `<< y` and `<< y` and `<< y` and `<< y`." -- Todo: "Erased all \"char y(34);\" and all \"<< y\"."
- dt "char *& f() { static char *p; cout << &p << endl; return p; } int main() { char *p = f(); cout << &p << endl; }"
- "char *& f() { static char *p; cout << &p << ' '; return p; } int main() { char *p = f(); cout << &p; }"
- "Replaced `<< endl` with `<< ' '`, and erased `<< endl`." -- Todo: say "first" and "last".
- putStrLn "All diff tests passed."
- where
- dt :: String → String → String → IO ()
- dt x y r = test_cmp x r $ show $ Editing.Diff.diff x y
- dt' :: String → String → String → String → IO ()
- dt' x y xy yx = do
- test_cmp x xy $ show $ Editing.Diff.diff x y
- test_cmp y yx $ show $ Editing.Diff.diff y x
- dts :: String → [(String, String)] → IO ()
- dts _ [] = return ()
- dts s ((s', d) : r) = dt s s' d >> dts s' r
- make_type_tests :: IO ()
- make_type_tests = do
- t "void(pointer)" $ Right "void(T *)"
- t "pointer to const pointer to long double" $ Right "long double*const *"
- t "function taking an int and returning nothing" $ Right "void(int )"
- let q = "void(int (* const (** (* const volatile (X::* volatile* (* )(int) )(char*)) [2])(long) ) [3])" in t q $ Right q
- t "function returning nothing and taking a pointer to a function returning a bool and taking an int" $ Right "void (bool (*)(int))"
- t "function taking a pointer to a (function returning a bool and taking an int), returning nothing" $ Right "void(bool (*)(int))"
- t "reference to a pointer to a function returning nothing, and taking an int" $ Right "void(*&)(int)"
- t "function taking an int, a char, a double, and returning nothing" $ Right "void(int, char, double)"
- t "function returning nothing and taking an int, a char, and a double" $ Right "void (int, char, double)"
- t "function returning a B<C<T>>" $ Right "B<C<T>>()"
- t "vector<T*>" $ Right "vector<T*>"
- t "function returning a ::B<T, (3>>2)>::value_type and taking a vector<vector<int>>" $ Right "::B<T, (3>>2)>::value_type (vector<vector<int>>)"
- t "function taking no arguments, returning a reference to an array of three pointers to functions taking integers and returning nothing" $ Right "void(*(&())[3])(int )"
- t "pointer to a constant volatile pointer to an array of 3 ints" $ Right "int(*volatile const *)[3]"
- t "function returning nothing and taking a reference to an array of three pointers to void" $ Right "void (void*(&)[3])"
- t "pointer to void(void)" $ Right "void(*)(void)"
- t "reference to pointer to const array" $ Right "T const (*&)[]"
- t "function taking a const (pointer to int) and a volatile function" $ Right "T (int*const , T ()volatile )"
- t "function taking two integers, three doubles, and returning a boolean" $ Right "bool(int, int, double, double, double)"
- t "function taking two pointers to integers" $ Right "T (int*, int*)"
- t "rvalue reference to function" $ Right "T (&&)()"
- t "constant constant pointer to volatile volatile int" $ Right "volatile volatile int*const "
- --t "pointer to a function from string_bla to int" $ Right "int(*)(string_bla )"
- t "pointer to " $ Left "Unexpected end of type description. Expected type description."
- t "pointer to function taking pointer to function" $ Right "T (*)(T (*)())"
- --t "pointer to int and double" $ Left "Unexpected \"a\" after \"to int \". Expected type-specifier, abstract-declarator, or end of type description."
- t "function returning " $ Left "Unexpected end of type description. Expected type description."
- t "function taking a pointer and a reference and returning a reference to a constant array" $ Right "T const (&(T *, T &))[]"
- t "array of " $ Left "Unexpected end of type description. Expected type description or integer-literal."
- t "foo bar bas" $ Left "Unexpected `bas` after `foo bar `. Expected \"::\" or template-arguments."
- t "array of seven characters" $ Right "char[7]"
- t "pointer to (function taking constant integer)*" $ Right "T (**)(const int)"
- t "pointer to void()" $ Right "void(*)()"
- t "function taking a pointer to void() returning a reference to an int[3]" $ Right "int(&(void(*)() ))[3]"
- t "void(pointer to function)" $ Right "void(T (*)())"
- t "function*(const int)" $ Right "T (*(const int))()"
- t "constant pointer to a function" $ Right "T (*const )()"
- t "(function taking an int[3] )*" $ Right "T (*)(int[3] )"
- t "(function*[3])&()" $ Right "T (*(&())[3])()"
- t "int(::T::U::V::**)" $ Right "int(::T::U::V::**)"
- t "int(X::*)()const volatile" $ Right "int(X::*)()const volatile"
- t "int volatile X::* Y::* const Z::*" $ Right "int volatile X::* Y::* const Z::*"
- {-
- t "pointer to a member function" $ Right "void(T::*)()"
- t "pointer to member integer" $ Right "int T::*"
- t "pointer to member" $ Right "T T::*"
- t "pointer to member pointer to member pointer to member array" $ Right "T(T::* T::* T::*)[]"
- -}
- t "array*const" $ Right "T (*const)[]"
- t "function taking (pointer to function returning int taking int) returning int" $ Right "int(int (*)(int))"
- --t "function+" $ Left "Unexpected \"+\" after \"function\". Expected \"taking\", \"returning\", \"from\", abstract-declarator, or end of type description."
- t "void(register pointer to string)" $ Right "void(register string*)"
- t "array of three arrays of 2 arrays of 1 integer" $ Right "int[3][2][1]"
- putStrLn "All make-type tests passed."
- where
- t :: String → Either String String → IO ()
- t i o = test_cmp i o (either (Left . id) (Right . Cxx.Show.show_simple) $ Cxx.Parse.makeType i)
- precedence_tests :: IO ()
- precedence_tests = do
- s "x::y" "x::y"
- s "if (b) int *ptr = new int(3), a(2);" "if (b) {int *ptr = (new int(3));int a(2);}"
- s "if(b) if(c) foo; else bar;" "if(b) { if(c) { foo; } else { bar; } }"
- s "a=b<c?d=e:f=g" "a=((b<c)?(d=e):(f=g))" -- Example from TC++PL, section 6.2.
- s "x?y?z?a:b:c:d" "x?(y?(z?a:b):c):d"
- s "*i-40?(*i-x?S(1,*i):a)+r(i+1,e,x,a):'('+(i[1]-46?r(i+1,o-1,x,a):'.'+r(i+2,o-1,x+1,a))+')'+r(o,e,x,a)" "((*i)-40)?((((*i)-x)?(S(1,(*i))):a)+(r((i+1),e,x,a))):((('('+(((i[1])-46)?(r((i+1),(o-1),x,a)):('.'+(r((i+2),(o-1),(x+1),a)))))+')')+(r(o,e,x,a)))" -- Taken from the lambda calculus snippet.
- s "x->x->*x.x.*x" "((x->x)->*(x.x)).*x"
- s "x || x && x | x ^ x bitand x == x < x << x" "x || (x && (x | (x ^ (x bitand (x == (x < (x << x)))))))"
- s "*++vector<int>{2,5,4}.rbegin()" "*(++(((vector<int>{2,5,4}).rbegin)()))"
- s "x---------x" "((((x--)--)--)--)-x"
- s "z+operator+(x,y)" "z+(operator+(x,y))"
- s "x.operator()() * operator new[ ]()" "((x.operator())()) * (operator new[ ]())"
- s "throw 2 + 1, throw, 9" "((throw (2 + 1)), throw), 9"
- s "x + x *= x + x /= x + x" "(x + x) *= ((x + x) /= (x + x))"
- s "(x)y + x(y)" "((x)y) + (x(y))"
- f "(x+y)z" "Unexpected `z` after (x+y). Expected postfix operator, binary operator, ternary operator, or end of code."
- s "a+++a, b++ +b, c+ ++c, d+++ +d, e+ +++e" "(((((a++)+a), ((b++) +b)), (c+ (++c))), ((d++)+ (+d))), (e+ (++(+e)))"
- s "x += operatornew, b(), !c" "((x += operatornew), (b())), (!c)"
- s "sizeof u + sizeof(x) + sizeof(y*z)" "((sizeof u) + sizeof(x)) + (sizeof(y*z))"
- s "x.template a<int>()" "(x.template a<int>)()"
- s "const_cast<vector<vector<int>>>(x)" "const_cast<vector<vector<int>>>(x)" -- Tricky closing angle brackets.
- s "x.~y" "x.~y"
- s "f (x+3,y)-g(x+3)" "(f ((x+3),y))-(g(x+3))"
- s "::x + y::z + a::b::c::d::e" "(::x + y::z) + a::b::c::d::e"
- s "x[y + 'z']" "x[y + 'z']" -- No parens around x + z or around 'z'.
- f "x*" "Unexpected end of code. Expected pm-expression."
- f "x && throw 3" "Unexpected `throw` after `x && `. Expected inclusive-or-expression."
- f "&operator" "Unexpected end of code. Expected overloadable operator or conversion-type-id."
- f "x.*" "Unexpected end of code. Expected cast-expression."
- f "x--x" "Unexpected `x` after x--. Expected postfix operator, binary operator, ternary operator, or end of code."
- f "x." "Unexpected end of code. Expected id-expression, \"template\", or pseudo-destructor-name."
- f "x-" "Unexpected end of code. Expected multiplicative-expression."
- f "x( " "Unexpected end of code. Expected \")\" or expression-list."
- f "x(y" "Unexpected end of code. Expected \")\", \"(\", braced-init-list, \"::\", template-arguments, postfix operator, binary operator, ternary operator, or comma."
- f "x?y" "Unexpected end of code. Expected colon, \"(\", braced-init-list, \"::\", template-arguments, postfix operator, binary operator, or ternary operator."
- f "x[" "Unexpected end of code. Expected expression or braced-init-list."
- f "x.operator foo bar()" "Unexpected `(` after `foo bar`. Expected \"::\" or template-arguments."
- putStrLn "All precedence tests passed."
- where
- s :: String → String → IO () -- Test for success.
- s i o = test_cmp i (Right o) (Cxx.Parse.precedence i)
- f :: String → String → IO () -- Test for failure.
- f i o = test_cmp i (Left o) (Cxx.Parse.precedence i)
- parse_tests :: IO ()
- parse_tests = do
- t "struct A<int>;"
- t "void f(int, ...);"
- t "{ if(int i = 3); }"
- t "int (::x::y);"
- putStrLn "All parse tests passed."
- where
- t :: String → IO ()
- t s = test_cmp s (Right s) $ fmap Cxx.Show.show_simple $ Cxx.Parse.parseRequest s
- main :: IO ()
- main = do
- basic_tests
- Editing.EditsPreparation.use_tests
- diff_tests
- make_type_tests
- precedence_tests
- parse_tests