PageRenderTime 184ms CodeModel.GetById 158ms app.highlight 18ms RepoModel.GetById 1ms app.codeStats 0ms

/src/Editing/Tests.hs

http://github.com/Eelis/geordi
Haskell | 464 lines | 409 code | 23 blank | 32 comment | 26 complexity | 3e418083181f2f751a6c7f5277af3a7b MD5 | raw file
  1{-# LANGUAGE UnicodeSyntax #-}
  2
  3module Main (main) where
  4
  5import qualified Editing.EditsPreparation
  6import qualified Editing.Parse
  7import qualified Editing.Execute
  8import qualified Editing.Diff
  9import qualified Cxx.Show
 10import qualified Cxx.Parse
 11
 12import Parsers (eof, parseOrFailE)
 13import Util (test_cmp, (<<), (.))
 14import Request (EditableRequest(..), EditableRequestKind(..))
 15
 16import Prelude hiding ((.))
 17import Data.SetOps
 18
 19basic_tests :: IO ()
 20basic_tests = do
 21  f "" "make foo bar bas" "Unexpected end of command. Expected \"::\" or template-arguments."
 22  f "" "make " "Unexpected end of command. Expected \"declaration\", \"body\", production-name, \"all\", \"any\", \"every\", \"each\", ordinal, or declarator-id."
 23  f "" "make i pointer to" "Unexpected end of command. Expected type description."
 24  s "mutable int i;" "make i const" "const mutable int i;"
 25  s "int i;" "make i a const double" "double const i;"
 26  s "int const i;" "make i a double" "double const i;"
 27  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); }"
 28    -- "bind(&g)(3, 2);" is determined not to be declaration because it would be a reference initialized with two arguments.
 29  s "int i;" "make i a *&" "int *& i;"
 30  s "int * p = f();" "make p auto" "auto p = f();"
 31  s "inline void f();" "make f noninline" "void f();"
 32  s "int (* const i)(double);" "make i nonconst" "int (* i)(double);"
 33  s "int i;" "make i a pointer&" "int *& i;"
 34  f "int i;" "make j const" "Could not find free declaration of j."
 35  s "void f() { int i; i; i = 0; }" "make i a pointer" "void f() { int * i; i; i = 0; }"
 36  s "struct X { static void f(); }" "append semicolon and make f pure" "struct X { virtual void f()= 0 ; };"
 37  s "struct X { virtual void f() = 0; };" "make f static" "struct X { static void f() ; };"
 38  s "struct X { void f(); };" "make f virtual pure const inline explicit" "struct X { virtual inline explicit void f()const = 0 ; };"
 39  s "struct X { ~X(); };" "make ~ X virtual" "struct X { virtual ~X(); };"
 40  s "struct X { virtual inline explicit void f()const = 0 ; };" "make f impure nonvirtual nonexplicit noninline" "struct X { void f()const ; };"
 41  s "struct X { X(int i); };" "make i a reference to const and make constructor explicit" "struct X { explicit X(const int & i); };"
 42  s "int *p;" "make p a const*volatile" "const int *volatile p;"
 43  s "void N::f() {}" "make N::f inline" "inline void N::f() {}"
 44  s "struct X { void operator++(); };" "make operator++ a const function returning an X&" "struct X { X & operator++()const ; };"
 45  s "int x /*haha*/ ; // ok dan /* mja */" "make x const" "const int x /*haha*/ ; // ok dan /* mja */"
 46  s "T const ( &f() )[3] { T x = {v}; }" "make f inline" "inline T const ( &f() )[3] { T x = {v}; }"
 47  s "int *i; int * & j;" "make i a pointer to a pointer" "int ** i; int * & j;"
 48  s "struct Factorial { static int v = N; };" "make v const" "struct Factorial { const static int v = N; };"
 49  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; }"
 50  s "int i;" "make i an array" "int i[];"
 51  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) {} }"
 52  s "void f() { try { long long i; } catch(long long j) {} }" "make i and j long" "void f() { try { long i; } catch(long j) {} }"
 53  s "int i;" "make i a const array" "const int i[];"
 54  s "int i;" "make i a const array of pointers" "int *const i[];"
 55  s "int i[];" "make i const" "const int i[];"
 56  s "struct X { ~X(); }" "append ; and make destructor virtual and show" "struct X { virtual ~X(); };"
 57  s "{ try{}catch(const int i){} }" "make i volatile" "{ try{}catch(volatile const int i){} }"
 58  s "void f(int i, double d){}" "make i and d long" "void f(long int i, long double d){}"
 59  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);"
 60  s "void f(float, int, char, double);" "make second and third parameter-declaration const" "void f(float, const int, const char, double);"
 61  s "{ if(int i = 3) ; }" "make i const" "{ if(const int i = 3) ; }"
 62  s "int i;" "make i an array of const" "const int i[];"
 63  s "int i;" "make i a static const function" "static int i()const ;"
 64  s "int i;" "make i a pointer to a function" "int (* i)();"
 65  s "int i;" "make i a pointer to a function taking two doubles" "int (* i)(double, double);"
 66  s "int i;" "make i a function returning a const" "const int i();"
 67  s "int i;" "make i a function returning a const pointer and taking a bool" "int *const i(bool);"
 68  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; }"
 69  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) {} }"
 70  f "void f(int i) { try {} catch(int j) {} }" "make j mutable" "Invalid decl-specifier for type-specifier-seq: mutable"
 71  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); };"
 72  s "struct X { operator ()(); };" "make operator() const" "struct X { operator ()()const ; };" -- Spaces don't matter when matching declarator-ids.
 73  s "<< 3, i; int i = 2;" "make i const" "<< 3, i; const int i = 2;"
 74  putStrLn "All make tests passed."
 75
 76  t "erase all 2 and insert x before second 3 and prepend y" $ Right "y1  3  x3 4 5"
 77  t "erase everything before last 2 and replace everything after 4 with x" $ Right "2 3 4x"
 78  t "insert x after all 2 and append y" $ Right "1 2x 3 2x 3 4 5y"
 79  t "erase first 2 and replace second 2 with x and omit last  " $ Right "1  3 x 3 45"
 80  t "erase first and last 2 and all 3 and 4 and everything before first 2 and everything after 4" $ Right "    "
 81  t "erase third last space and kill everything after second last  " $ Right "1 2 3 23 "
 82  t "insert x after 1 2 and before all 3 and erase 5 and prepend y" $ Right "y1 2x x3 2 x3 4 "
 83  t "erase everything before 4 and everything after 5" $ Right "4 5"
 84  t "insert x before 3 4 and 5" $ Right "1 2 3 2 x3 4 x5"
 85  t "insert x after 1 and all 3 and before 5 and erase 4" $ Right "1x 2 3x 2 3x  x5"
 86  t "erase second space before 4" $ Right "1 2 3 23 4 5"
 87  t "erase first 2 3 and 3 2 and 4 5 and last  " $ Right "1  3 "
 88  t "move 1 till second 3 to before 5" $ Right "3 4 1 2 3 2 5"
 89  t "move 1 till after second 3 to before 5" $ Right " 4 1 2 3 2 35"
 90  t "swap last 2 3 and last space before 4" $ Right "1 2 3  2 34 5"
 91  t "swap last 2 3 with last space before 4" $ Right "1 2 3  2 34 5"
 92  t "swap 1 and first 3 and second 3 and 5" $ Right "3 2 1 2 5 4 3"
 93  t "replace 2 after second space with x" $ Right "1 2 3 x 3 4 5"
 94  t "move everything till 4  to end and erase 4 " $ Right "51 2 3 2 3 "
 95  t "erase everything" $ Right ""
 96  t "insert x after second space before 4" $ Right "1 2 3 2 x3 4 5"
 97  t "add < and > around second 3" $ Right "1 2 3 2 <3> 4 5"
 98  t "add braces around everything" $ Right "{1 2 3 2 3 4 5}"
 99  t "move everything after second 3 to begin" $ Right " 4 51 2 3 2 3"
100  t "move second 3 to end and 5 to begin" $ Right "51 2 3 2  4 3"
101  t "erase first space until second space before 4" $ Right "1 3 4 5"
102  t "erase spaces" $ return "1232345"
103  t "erase second last space before 4" $ Right "1 2 3 23 4 5"
104  t "erase after second 2" $ Right "1 2 3 2"
105  t "erase after second 2 until before 5" $ Right "1 2 3 25"
106  t "erase 1 and erase 1" $ Right " 2 3 2 3 4 5"
107  t "erase before second last space" $ Right " 4 5"
108  t "move 4 5 to before 1 and erase everything after second 2" $ Right "4 51 2 3 2"
109  t "erase everything between last and first 2" $ Right "1 22 3 4 5"
110  t "erase everything between second 2 and begin" $ Right "2 3 4 5"
111  t "erase all space between second 2 and 4" $ Right "1 2 3 234 5"
112  t "erase from first 3 until after everything" $ Right "1 2 "
113  t "erase 2 after and before first 3" $ return "1  3  3 4 5"
114  t "add + before and after 4" $ return "1 2 3 2 3 +4+ 5"
115  t "move before second 3 until 4 to begin" $ Right "3 1 2 3 2 4 5"
116  t "erase everything between begin and end" $ Right ""
117  t "move everything between first 3 and 4 to begin" $ Right " 2 3 1 2 34 5"
118  t "erase before second 3 until 4" $ Right "1 2 3 2 4 5"
119  t "insert x before second 3 and at end" $ Right "1 2 3 2 x3 4 5x"
120  t "erase until after second 3" $ Right " 4 5"
121  t "erase from before second 3" $ Right "1 2 3 2 "
122  t "replace all but first and second last space with x" $ Right "1 2x3x2x3 4x5"
123  t "change all but first and second last space to x" $ Right "1 2x3x2x3 4x5"
124  t "erase between second and fourth space and 1" $ Right " 2  3 4 5"
125  t "erase between the first and third space and prepend x" $ Right "x1  2 3 4 5"
126  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)"
127  t "move from first 3 until 4 to begin" $ Right "3 2 3 41 2  5"
128  t "erase everything from before everything until the second 3" $ Right "3 4 5"
129  t "add parentheses around first 2 and 5" $ Right "1 (2) 3 2 3 4 (5)"
130  t "erase everything between first space and last space" $ Right "1  5"
131  t "erase all 3 and all 2 between begin and end" $ Right "1     4 5"
132  t "erase everything between second and first 2 " $ Right "1 2 2 3 4 5"
133  t "erase from second 2 till last space" $ Right "1 2 3 5"
134  t "erase from second 2 until after 3 and add x before 4" $ Right "1 2 3  x4 5"
135  -- t "erase everything between 1 and the second 2 and everything between 4 and 5" $ Right "12 3 45"
136  t "erase from before 4 until end" $ Right "1 2 3 2 3 "
137  t "use 5x and y4" $ Right "1 2 3 2 3 y4 5x"
138  t "erase everything from after 1 until second last space" $ Right "1 4 5"
139  t "add parentheses around everything between 1 and second space before 4" $ Right "1( 2 3 2) 3 4 5"
140  t "add + and - around all 3 and second 2 and prepend x" $ Right "x1 2 +3- +2- +3- 4 5"
141  t "move 4 till end to front" $ Right "4 51 2 3 2 3 "
142  t "erase all space after first 2" $ Right "1 232345"
143  t "add x before first 3 after second 2" $ Right "1 2 3 2 x3 4 5"
144  t "add x before second space after second 3" $ Right "1 2 3 2 3 4x 5"
145  t "add x after all space before first 3" $ Right "1 x2 x3 2 3 4 5"
146  t "erase all space before last 3" $ Right "12323 4 5"
147  t "erase second 2 till end" $ Right "1 2 3 "
148  t "append x before 5 and prepend y before all 2 between first 3 and 5" $ Right "1 2 3 y2 3 4 x5"
149  t "move everything after second 3 to begin" $ Right " 4 51 2 3 2 3"
150  t "replace first 2 with x and replace all 2 with x" $ Right "1 x 3 x 3 4 5"
151  t "erase everything until 4 and 5" $ Right "4 "
152  t "erase 3 2 till 5" $ Right "1 2 5"
153  t "move second 2 to back and prepend x" $ Right "x1 2 3  3 4 52"
154  t "cut everything before first 2 and first and second 3 and everything after 4 and prepend x" $ Right "x2  2  4"
155  t "replace all 2 with 3 and erase all 3 and add x after second 2" $ Right "1 3  3x  4 5"
156  t "insert spacer before 4 and insert a semicolon after 1 and erase last space" $ Right "1; 2 3 2 3 spacer45"
157  t "erase first and second last  " $ Right "12 3 2 34 5"
158  t "replace 1 with x and all 2 with y and erase second 3" $ Right "x y 3 y  4 5"
159  t "move everything after last 3 to front and erase 5" $ Right " 4 1 2 3 2 3"
160  t "erase spaces around first 2" $ Right "123 2 3 4 5"
161  t "erase spaces around 3 after second 2" $ Right "1 2 3 234 5"
162  t "erase 1 and 2 around first space" $ Right "  3 2 3 4 5"
163  t "erase all but first two spaces" $ Right "1 2 32345"
164  t "add x after 4 and add y after 4" $ Right "1 2 3 2 3 4yx 5"
165  t "erase 4 and add y before 4 and add x after 4" $ Right "1 2 3 2 3 yx 5"
166  t "move 4 to end and insert x before 5" $ Right "1 2 3 2 3  x54"
167  t "erase 4 and move 5 to begin" $ Right "51 2 3 2 3  "
168  t "move 3 2 3 to front and insert x before second 2" $ Right "3 x2 31 2  4 5"
169  t "append float x; int y;" $ Right "1 2 3 2 3 4 5float x; int y;"
170  t "erase 5 and move everything after last 3 to front" $ Right " 4 1 2 3 2 3"
171  t "move everything before 4 to end and move first 3 to front" $ Right "34 51 2  2 3 "
172  t "move 3 4 5 to before 4" $ Left "Move destination lies in source range."
173  t "move 1 and 4 to after first 3" $ Right " 2 314 2 3  5"
174  -- Order-sensitive edits:
175  t "add parentheses around everything and append x" $ Right "(1 2 3 2 3 4 5)x"
176  t "add parentheses around all 3 and all 2 and erase 4" $ Right "1 (2) (3) (2) (3)  5"
177  t "append x and add parentheses around everything" $ Right "(1 2 3 2 3 4 5x)"
178  t "append x after everything before 4 and add y before 4" $ Right "1 2 3 2 3 xy4 5"
179  t "insert y before 4 and insert z after second 3 " $ Right "1 2 3 2 3 zy4 5"
180  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 "
181  t "add parentheses around everything and prepend x" $ Right "x(1 2 3 2 3 4 5)"
182  t "prepend x and add parentheses around everything" $ Right "(x1 2 3 2 3 4 5)"
183  t "prepend x before everything after 4 and add y after 4" $ Right "1 2 3 2 3 4yx 5"
184  t "add y after 4 and prepend x before everything after 4" $ Right "1 2 3 2 3 4xy 5"
185  -- Semantic edits:
186  ct "a x;" "add b after first identifier" $ Right "ab x;"
187  ct "struct X { operator bool() { return true; } };" "move declaration of operator bool to end" $ Right "struct X { };operator bool() { return true; } "
188  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(); };"
189  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;}"
190  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;};"
191  ct "void f() { cout << 3; g(); }" "erase everything from after 3; until after body of f" $ Right "void f() { cout << 3;}"
192  ct "int main() { cout << 3; }" "move << 3 to front and erase declaration of main" $ Right "<< 3"
193  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};"
194  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();"
195  ct "struct X { void f(); }; struct Y { void f(); };" "erase declaration of f in Y" $ Right "struct X { void f(); }; struct Y { };"
196  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(); } "
197  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"
198  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() { }"
199  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; }"
200  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;}"
201  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 { } } } }"
202  ct "struct X { X(int); };" "erase second declaration of X" $ Right "struct X { };"
203  ct "template <typename> void f(); void f(int);" "erase second declaration of f" $ Right "template <typename> void f(); "
204  ct "struct X { template <typename U> X(U); };" "erase second declaration of X" $ Right "struct X { };"
205  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(); };"
206  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(); }; "
207  ct "void f(int i);" "erase declaration of i" $ Right "void f();"
208  ct "struct X { int i; };" "erase declaration of i" $ Right "struct X { };"
209  ct "{ 3; 4; 5; }" "swap first and last statement" $ Right "{ 5; 4; 3; }"
210  ct "{ 3; 4; 5; }" "swap statements around 4;" $ Right "{ 5; 4; 3; }"
211  ct "{ 3; 4; 5; 6; }" "swap statements before 5 with last statement" $ Right "{ 6; 5; 3; 4; }"
212  ct "void f(int,double,char);" "swap first two parameter-declarations" $ return "void f(double,int,char);"
213--todo:  ct "{ if(b) 3; 4; 5; }" "add curlies around first two statements after if" $ Right "{ if(b) {3; 4;} 5; }"
214--todo:  ct "{ 3; 4; 5; }" "add curlies around first and second statement" $ Right "{ {3; 4;} 5; }"
215  ct "{ 3; 4; 5; }" "add curlies around first statement and around second statement" $ Right "{ {3;} {4;} 5; }"
216  ct "<< max(3, 2, 1)" "add curlies around code between parens" $ return "<< max({3, 2, 1})"
217  ct "{ 1;2;3;4;5; }" "swap first two statements with last two statements" $ Right "{ 4;5; 3;1;2;}"
218  ct "{ 1;2;3; }" "swap first two statements" $ Right "{ 2;1;3; }"
219  --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;}"
220  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;"
221  ct "template <typename T, int i> struct S;" "erase second template-parameter" $ return "template <typename T> struct S;"
222  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);"
223  ct "int f();" "replace type-specifier with void" $ Right "void f();"
224  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; }"
225  ct "int a;in@@@t x;int y;int z;" "erase @@@ and erase int a; and erase second declaration" $ Right "int y;int z;"
226  ct "@     int x;" "erase @ and replace declaration of x by bla" $ return "     bla"
227  ct "@@@@@ void f(){} int x;"  "erase @@@@@ and erase first x after function-definition" $ Right " void f(){} int ;"
228  ct "@@@@int x; int y; int z;" "erase @@@@ and erase from start until second declaration" $ Right "int z;"
229  ct "@@@@int x; int y; int z;" "erase @@@@ and erase from second declaration until last space" $ Right "int x; z;"
230  ct "class X extends Y { int i:2; };" "replace extends with : and replace literal after : with 3" $ Right "class X : Y { int i:3; };"
231  ct "T f() { 0;x; } U y;" "erase everything after 0 in f" $ Right "T f() { 0} U y;"
232  ct "T f() { 0;x; } U y;" "erase everything before x in f" $ Right "T f() { x; } U y;"
233  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;"
234  ct ";     void g() {} void f() { {1;} }" "erase first semicolon and erase curlies around 1;" $ return "     void g() {} void f() { 1; }"
235  -- Edit errors:
236  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."
237  t "erase second 4 after 1" $ Left "String `4` does not occur twice after 1."
238  t "move second 2 to x" $ Left "Unexpected `x` after `second 2 to `. Expected \"beginning\", \"begin\", \"front\", \"start\", \"end\", \"back\", \"before\", or \"after\"."
239  t "replace alligators with chickens" $ Left "String `alligators` does not occur."
240  t "use banana" $ Left "No non-exact match for banana."
241  t "use 5426" $ Left "No non-exact match for 5426."
242  t "erase 2" $ Left "String `2` occurs multiple times."
243  t "replace 1 and erase with 4" $ Left "String `erase` does not occur."
244  t "replace tenth last 2 by x" $ Left "String `2` does not occur 10 times."
245  t "erase second 9" $ Left "String `9` does not occur."
246  t "replace all 2 with 3 and replace second 2 with x" $ Left "Overlapping edits: replace 2 with 3 and replace 2 with x."
247  t "erase everything before first 3 and replace first 2 with x" $ Left "Overlapping edits: erase `1 2 ` and replace 2 with x."
248  t "erase 5 between 1 and 4" $ Left "String `5` does not occur between 1 and 4."
249  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."
250  -- Syntax errors:
251  t "isnert 3 before 4" $ Left "Unexpected `isnert` at start. Expected edit command."
252  t "insert " $ Left "Unexpected end of command. Expected option, wrapping description, or verbatim string."
253  t "insert kung fu" $ Left "Unexpected end of command. Expected \" and\", \" in\", \" at\", \" around\", \" before\", or \" after\"."
254  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."
255  t "move x " $ Left "Unexpected end of command. Expected \" till\", \" until\", \" around\", \" before\", \" after\", \" between\", \" in\", \" and\", or \" to\"."
256  t "move x to "$ Left "Unexpected end of command. Expected \"beginning\", \"begin\", \"front\", \"start\", \"end\", \"back\", \"before\", or \"after\"."
257  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."
258  putStrLn "All basics tests passed."
259
260 where
261  ct :: String  String  Either String String  IO ()
262  ct x c o = test_cmp c o $ case parseOrFailE (Editing.Parse.commandsP << eof) c "command" of
263    Left e  Left e
264    Right (cmds, _)  editable_body . Editing.Execute.execute Nothing cmds (EditableRequest (Evaluate ()) x)
265
266  s, f :: String  String  String  IO ()
267  s code cmdstring expectation = ct code cmdstring (Right expectation) -- test for success
268  f code cmdstring expectation = ct code cmdstring (Left expectation) -- test for failure
269
270  t = ct "1 2 3 2 3 4 5"
271
272diff_tests :: IO ()
273diff_tests = do
274
275  dt' "foo; bar; monkey; chicken; bas;" "bar; monkey; chicken;" "Erased `foo;` and `bas;`." "Prepended `foo;` and appended `bas;`."
276
277  dt' "{ fstream f(\"t.cpp\"); string s(istreambuf_iterator<char>(f), istreambuf_iterator<char>()); }"
278    "{ fstream f(\"t.cpp\"); string s((istreambuf_iterator<char>(f)), istreambuf_iterator<char>()); }"
279    "Inserted ( before `istreambuf_iterator<char>`, and inserted ) after `istreambuf_iterator<char>(f)`."
280    "Erased ( before `istreambuf_iterator<char>` and ) after `istreambuf_iterator<char>(f)`."
281        -- Todo: One day, the former should say "wrapped ...".
282
283  dt' "int f(int & i) { i = 4; return i;} int g(int && i){return f(i);} int main() { cout << g(2); }"
284    "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); }"
285    "Replaced `int f` with `int & f`, replaced `int g` with `int & g`, and inserted `int & g(int & i){return f(i);}` before `int main`."
286    "Replaced `int & f` with `int f`, replaced `int & g` with `int g`, and erased `int & g(int & i){return f(i);}`."
287
288  dt' "{string foo = \"kangaroo\"; auto m = foo.find_first_of('m'); cout << *m;}"
289    "{string foo = \"kangaroo\"; size_t m = foo.find_first_of('m'); cout << foo[m];}"
290    "Replaced `auto m` with `size_t m`, and replaced `<< *m` with `<< foo[m]`."
291    "Replaced `size_t m` with `auto m`, and replaced `<< foo[m]` with `<< *m`."
292      -- Todo: Group.
293
294  dt "{int i=0,t=time(0);for(;i<5000000;i++)asm(\".org 0xffff\");cout << time(0)-t; }"
295    "{int i=0,t=time(0);for(;i<5000;i++)int tmp=1*88+71/4000^66;cout << time(8)-t; }"
296    "Replaced i<5000000 with i<5000, replaced `asm(\".org 0xffff\")` with `int tmp=1*88+71/4000^66`, and replaced 0 with 8."
297
298  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; }"
299    "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); }"
300    "Replaced cf with curr_func, inserted `<< \": \" << a` after `<< cfun.name`, and replaced `cout << haha` with haha(42)."
301    "Replaced curr_func with cf, erased `<< \": \" << a`, and replaced haha(42) with `cout << haha`."
302
303  dt "{float i=0,t=time(0);for(;i<5000000;i++) { if(x == 3) f(reinterpret_cast<long>(x)); } }"
304    "{int i=0,t=time(null);for(;i<5000000;++i) { if(x != 3) f(static_cast<long>(x)); } }"
305    "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>`."
306{-
307  dt' "struct a { int b; a():b([]{ return 1 + 2 + 3; }){}}a_; int main() { cout << a_.b }"
308    "struct a { int b; a({}):b([]{ return 1 + 2 + 3; }()){}}a_; int main() { cout << a_.b; }"
309    "Replaced \"a():b([]{\" with \"a({}):b([]{\", replaced \")\" after \"return 1 + 2 + 3; }\" with \"())\", and inserted \";\" after \"cout << a_.b\"."
310    "Replaced \"a({}):b([]{\" with \"a():b([]{\", replaced \"}()){}}a_\" with \"}){}}a_\", and erased \";\" after \"cout << a_.b\"."
311-}
312  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; }"
313    "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; }"
314    "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`."
315{-
316  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); } }"
317    "{ 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); } }"
318    "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`."
319-}
320  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(); }"
321    "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(); }"
322    "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\"."
323
324  dt "char *& f() { static char *p; cout << &p << endl; return p; } int main() { char *p = f(); cout << &p << endl; }"
325    "char *& f() { static char *p; cout << &p << ' '; return p; } int main() { char *p = f(); cout << &p; }"
326    "Replaced `<< endl` with `<< ' '`, and erased `<< endl`." -- Todo: say "first" and "last".
327
328  putStrLn "All diff tests passed."
329 where
330  dt :: String  String  String  IO ()
331  dt x y r = test_cmp x r $ show $ Editing.Diff.diff x y
332  dt' :: String  String  String  String  IO ()
333  dt' x y xy yx = do
334    test_cmp x xy $ show $ Editing.Diff.diff x y
335    test_cmp y yx $ show $ Editing.Diff.diff y x
336  dts :: String  [(String, String)]  IO ()
337  dts _ [] = return ()
338  dts s ((s', d) : r) = dt s s' d >> dts s' r
339
340make_type_tests :: IO ()
341make_type_tests = do
342  t "void(pointer)" $ Right "void(T *)"
343  t "pointer to const pointer to long double" $ Right "long double*const *"
344  t "function taking an int and returning nothing" $ Right "void(int )"
345  let q = "void(int (* const (** (* const volatile (X::* volatile* (* )(int) )(char*)) [2])(long) ) [3])" in t q $ Right q
346  t "function returning nothing and taking a pointer to a function returning a bool and taking an int" $ Right "void (bool (*)(int))"
347  t "function taking a pointer to a (function returning a bool and taking an int), returning nothing" $ Right "void(bool (*)(int))"
348  t "reference to a pointer to a function returning nothing, and taking an int" $ Right "void(*&)(int)"
349  t "function taking an int, a char, a double, and returning nothing" $ Right "void(int, char, double)"
350  t "function returning nothing and taking an int, a char, and a double" $ Right "void (int, char, double)"
351  t "function returning a B<C<T>>" $ Right "B<C<T>>()"
352  t "vector<T*>" $ Right "vector<T*>"
353  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>>)"
354  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 )"
355  t "pointer to a constant volatile pointer to an array of 3 ints" $ Right "int(*volatile const *)[3]"
356  t "function returning nothing and taking a reference to an array of three pointers to void" $ Right "void (void*(&)[3])"
357  t "pointer to void(void)" $ Right "void(*)(void)"
358  t "reference to pointer to const array" $ Right "T const (*&)[]"
359  t "function taking a const (pointer to int) and a volatile function" $ Right "T (int*const , T ()volatile )"
360  t "function taking two integers, three doubles, and returning a boolean" $ Right "bool(int, int, double, double, double)"
361  t "function taking two pointers to integers" $ Right "T (int*, int*)"
362  t "rvalue reference to function" $ Right "T (&&)()"
363  t "constant constant pointer to volatile volatile int" $ Right "volatile volatile int*const "
364  --t "pointer to a function from string_bla to int" $ Right "int(*)(string_bla )"
365  t "pointer to " $ Left "Unexpected end of type description. Expected type description."
366  t "pointer to function taking pointer to function" $ Right "T (*)(T (*)())"
367  --t "pointer to int and double" $ Left "Unexpected \"a\" after \"to int \". Expected type-specifier, abstract-declarator, or end of type description."
368  t "function returning " $ Left "Unexpected end of type description. Expected type description."
369  t "function taking a pointer and a reference and returning a reference to a constant array" $ Right "T const (&(T *, T &))[]"
370  t "array of " $ Left "Unexpected end of type description. Expected type description or integer-literal."
371  t "foo bar bas" $ Left "Unexpected `bas` after `foo bar `. Expected \"::\" or template-arguments."
372  t "array of seven characters" $ Right "char[7]"
373  t "pointer to (function taking constant integer)*" $ Right "T (**)(const int)"
374  t "pointer to void()" $ Right "void(*)()"
375  t "function taking a pointer to void() returning a reference to an int[3]" $ Right "int(&(void(*)() ))[3]"
376  t "void(pointer to function)" $ Right "void(T (*)())"
377  t "function*(const int)" $ Right "T (*(const int))()"
378  t "constant pointer to a function" $ Right "T (*const )()"
379  t "(function taking an int[3] )*" $ Right "T (*)(int[3] )"
380  t "(function*[3])&()" $ Right "T (*(&())[3])()"
381  t "int(::T::U::V::**)" $ Right "int(::T::U::V::**)"
382  t "int(X::*)()const volatile" $ Right "int(X::*)()const volatile"
383  t "int volatile X::* Y::* const Z::*" $ Right "int volatile X::* Y::* const Z::*"
384{-
385  t "pointer to a member function" $ Right "void(T::*)()"
386  t "pointer to member integer" $ Right "int T::*"
387  t "pointer to member" $ Right "T T::*"
388  t "pointer to member pointer to member pointer to member array" $ Right "T(T::* T::* T::*)[]"
389-}
390  t "array*const" $ Right "T (*const)[]"
391  t "function taking (pointer to function returning int taking int) returning int" $ Right "int(int (*)(int))"
392  --t "function+" $ Left "Unexpected \"+\" after \"function\". Expected \"taking\", \"returning\", \"from\", abstract-declarator, or end of type description."
393  t "void(register pointer to string)" $ Right "void(register string*)"
394  t "array of three arrays of 2 arrays of 1 integer" $ Right "int[3][2][1]"
395  putStrLn "All make-type tests passed."
396 where
397  t :: String  Either String String  IO ()
398  t i o = test_cmp i o (either (Left . id) (Right . Cxx.Show.show_simple) $ Cxx.Parse.makeType i)
399
400precedence_tests :: IO ()
401precedence_tests = do
402  s "x::y" "x::y"
403  s "if (b) int *ptr = new int(3), a(2);" "if (b) {int *ptr = (new int(3));int a(2);}"
404  s "if(b) if(c) foo; else bar;" "if(b) { if(c) { foo; } else { bar; } }"
405  s "a=b<c?d=e:f=g" "a=((b<c)?(d=e):(f=g))" -- Example from TC++PL, section 6.2.
406  s "x?y?z?a:b:c:d" "x?(y?(z?a:b):c):d"
407  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.
408  s "x->x->*x.x.*x" "((x->x)->*(x.x)).*x"
409  s "x || x && x | x ^ x bitand x == x < x << x" "x || (x && (x | (x ^ (x bitand (x == (x < (x << x)))))))"
410  s "*++vector<int>{2,5,4}.rbegin()" "*(++(((vector<int>{2,5,4}).rbegin)()))"
411  s "x---------x" "((((x--)--)--)--)-x"
412  s "z+operator+(x,y)" "z+(operator+(x,y))"
413  s "x.operator()() * operator new[ ]()" "((x.operator())()) * (operator new[ ]())"
414  s "throw 2 + 1, throw, 9" "((throw (2 + 1)), throw), 9"
415  s "x + x *= x + x /= x + x" "(x + x) *= ((x + x) /= (x + x))"
416  s "(x)y + x(y)" "((x)y) + (x(y))"
417  f "(x+y)z" "Unexpected `z` after (x+y). Expected postfix operator, binary operator, ternary operator, or end of code."
418  s "a+++a, b++ +b, c+ ++c, d+++ +d, e+ +++e" "(((((a++)+a), ((b++) +b)), (c+ (++c))), ((d++)+ (+d))), (e+ (++(+e)))"
419  s "x += operatornew, b(), !c" "((x += operatornew), (b())), (!c)"
420  s "sizeof u + sizeof(x) + sizeof(y*z)" "((sizeof u) + sizeof(x)) + (sizeof(y*z))"
421  s "x.template a<int>()" "(x.template a<int>)()"
422  s "const_cast<vector<vector<int>>>(x)" "const_cast<vector<vector<int>>>(x)" -- Tricky closing angle brackets.
423  s "x.~y" "x.~y"
424  s "f  (x+3,y)-g(x+3)" "(f  ((x+3),y))-(g(x+3))"
425  s "::x + y::z + a::b::c::d::e" "(::x + y::z) + a::b::c::d::e"
426  s "x[y + 'z']" "x[y + 'z']" -- No parens around x + z or around 'z'.
427  f "x*" "Unexpected end of code. Expected pm-expression."
428  f "x && throw 3" "Unexpected `throw` after `x && `. Expected inclusive-or-expression."
429  f "&operator" "Unexpected end of code. Expected overloadable operator or conversion-type-id."
430  f "x.*" "Unexpected end of code. Expected cast-expression."
431  f "x--x" "Unexpected `x` after x--. Expected postfix operator, binary operator, ternary operator, or end of code."
432  f "x." "Unexpected end of code. Expected id-expression, \"template\", or pseudo-destructor-name."
433  f "x-" "Unexpected end of code. Expected multiplicative-expression."
434  f "x( " "Unexpected end of code. Expected \")\" or expression-list."
435  f "x(y" "Unexpected end of code. Expected \")\", \"(\", braced-init-list, \"::\", template-arguments, postfix operator, binary operator, ternary operator, or comma."
436  f "x?y" "Unexpected end of code. Expected colon, \"(\", braced-init-list, \"::\", template-arguments, postfix operator, binary operator, or ternary operator."
437  f "x[" "Unexpected end of code. Expected expression or braced-init-list."
438  f "x.operator foo bar()" "Unexpected `(` after `foo bar`. Expected \"::\" or template-arguments."
439  putStrLn "All precedence tests passed."
440 where
441  s :: String  String  IO () -- Test for success.
442  s i o = test_cmp i (Right o) (Cxx.Parse.precedence i)
443  f :: String  String  IO () -- Test for failure.
444  f i o = test_cmp i (Left o) (Cxx.Parse.precedence i)
445
446parse_tests :: IO ()
447parse_tests = do
448  t "struct A<int>;"
449  t "void f(int, ...);"
450  t "{ if(int i = 3); }"
451  t "int (::x::y);"
452  putStrLn "All parse tests passed."
453 where
454  t :: String  IO ()
455  t s = test_cmp s (Right s) $ fmap Cxx.Show.show_simple $ Cxx.Parse.parseRequest s
456
457main :: IO ()
458main = do
459  basic_tests
460  Editing.EditsPreparation.use_tests
461  diff_tests
462  make_type_tests
463  precedence_tests
464  parse_tests