/**
 * Unit tests for SSL's string module.
 *
 * @copyright See bottom.
 */
module string-test
imports libstratego-lib
strategies 

  main = 
    test-suite(!"string-test",
      explode-implode-test
    ; strcat-tests
    ; strlen-tests
    ; concat-strings-tests
    ; quote-tests
    ; padd-with-test
    ; is-substring-tests
    ; copy-char-test
    ; upper-case-test
    ; escape-tests
    ; string-sort-test
    ; string-tokenize-test
    ; split-tests
    ; string-replace-test
    )

strategies

  strcat-tests =
      apply-test(!"strcat-1", strcat, !("",  ""), !"")
    ; apply-test(!"strcat-2", strcat, !("a", ""), !"a")
    ; apply-test(!"strcat-3", strcat, !("",  "a"), !"a")
    ; apply-test(!"strcat-4", strcat, !("hello ",  "world"), !"hello world")

  strlen-tests =
      apply-test(!"strlen-1", strlen, !"", !0)
    ; apply-test(!"strlen-2", strlen, !"a", !1)
    ; apply-test(!"strlen-3", strlen, !"hello world", !11)

  concat-strings-tests =
      apply-test(!"concat-strings-1", concat-strings, ![], !"")
    ; apply-test(!"concat-strings-2", concat-strings, !["a", ""], !"a")
    ; apply-test(!"concat-strings-3", concat-strings, !["",  "a"], !"a")
    ; apply-test(!"concat-strings-4", concat-strings, !["hello ",  "world"], !"hello world")

    // tests for lists with annotations
    ; apply-test(!"concat-strings-5", concat-strings, !["hello ",  "world"]{1}, !"hello world")
    ; apply-test(!"concat-strings-6", concat-strings, !["hello"]{1}, !"hello")
    ; apply-test(!"concat-strings-7", concat-strings, ![]{1}, !"")
  
strategies  // for testing quote strategies
  
  quote-tests =    
    single-quote-test 
  ; un-double-quote-test
  ; is-double-quote-test
    
  single-quote-test =
    apply-test(!"single-quote-test",single-quote,!"foobar",!"'foobar'")

  un-double-quote-test =
    apply-test(!"un-double-quote-test", un-double-quote, !"\"fnord\"", !"fnord")
    
  is-double-quote-test =
    apply-test(!"is-double-quote 1"
    , is-double-quoted
    , !"\"fnord\""
    , !"\"fnord\""
    )
  ; apply-and-fail(!"is-double-quote 2"
    , is-double-quoted
    , !"fnord"
    )
  ; apply-and-fail(!"is-double-quote 3"
    , is-double-quoted
    , !"\"fnord"
    )
  ; apply-and-fail(!"is-double-quote 4"
    , is-double-quoted
    , !""
    )
  ; apply-test(!"is-double-quote 5"
    , is-double-quoted
    , !"\"\""
    , !"\"\""    
    )
  ; apply-test(!"is-double-quote 6"
    , is-double-quoted
    , !"\" \""
    , !"\" \""    
    )

strategies // for testing text split strategies
    
  split-tests =
    split-before-test
  ; split-after-test
  ; split-at-dot-test
  
  split-before-test =
    apply-test(!"split-before-test"
    , split-before
    , !("barfoofnord","foo")
    , !("bar","foofnord")
    )

  split-after-test =
    apply-test(!"split-after-test"
    , split-after
    , !("barfoofnord","foo")
    , !("barfoo","fnord")
    )

  split-at-dot-test =
    apply-test(!"split-at-dot-test"
    , split-at-dot
    , !"3.141592"
    , !("3","141592")
    )

strategies // for testing escape strategies
  
  escape-tests =
    escape-test
  ; unescape-test
    
  escape-test =
    apply-test(!"escape-test1"
    , escape
    , !"\"ab\\c"
    , !"\\\"ab\\\\c"
    )
  ; apply-test(!"escape-test2"
    , cify
    , !"a-b_c'"
    , !"a_b__c_p_"
    )

  unescape-test =
    apply-test(!"unescape-test1"
    , [unescape]
    , !["\\\"ab\\\\c"]
    , !["\"ab\\c"]
    )
  ; apply-test(!"unescape-test2"
    , [un-double-quote; unescape]
    , !["\" \\\\\\n\\t\""]
    , ![" \\\n\t"]
    )
  ; apply-test(!"unescape-test3"
    , [unescape]
    , ![" \\\\\\na\\b"]
    , ![" \\\na\\b"]
    )
  ; apply-test(!"unescape-test4"
    , [unescape]
    , !["\" \\\\\\n\\\\t\""]
    , !["\" \\\n\\t\""]
    )
    
strategies

  explode-implode-test =
    apply-test(!"explode-implode-test1"
    , explode-string; implode-string
    , !"foOBaR"
    , !"foOBaR"
    )
  ; apply-test(!"explode-implode-test2"
    , explode-string; implode-string
    , !"\n\t"
    , !"\n\t"
    )
  ; apply-and-fail(!"implode-string applied to non list"
    , implode-string
    , !"foo"
    )
  ; apply-and-fail(!"implode-string applied to non list"
    , implode-string
    , !1
    )
  ; apply-test(!"implode-string on simple list."
    , implode-string
    , !['a', 'b', 'c']
    , !"abc"
    )
  ; apply-test(!"implode-string on empty list."
    , implode-string
    , ![]
    , !""
    )
  ; apply-test(!"implode-string on empty list with annotation."
    , implode-string
    , ![]{1}
    , !""
    )
  ; apply-test(!"implode-string on list where nil has annotation."
    , implode-string
    , !['a', 'b', 'c' | []{1} ]
    , !"abc"
    )
  ; apply-test(!"implode-string on list where nil has annotation."
    , implode-string
    , !['a', 'b', 'c']{1}
    , !"abc"
    )

  upper-case-test = 
    apply-test(!"upper-case-test",upper-case,!"foOBaR",!"FOOBAR")

/**
 * is-substring
 */
strategies

  is-substring-tests = id
    ; is-substring-test(|"foo", "barfoofnord")
    ; is-substring-test(|"foo", "foo")
    ; is-substring-test(|"foo", "barfoo")
    ; is-substring-test(|"foo", "foobar")
    ; is-substring-test(|"foo", "foofoo")
    ; is-substring-test(|"f", "f")
    ; is-substring-test(|"f", "foo")
    ; not-is-substring-test(|"foo", "")
    ; not-is-substring-test(|"f", "")
    ; not-is-substring-test(|"foo", "fobar")

  is-substring-test(|substring, string) = 
    apply-test(!"is-substring-test"
    , is-substring(!substring)
    , !string
    , id
    )

  not-is-substring-test(|substring, string) = 
    apply-and-fail(!"is-substring-test"
    , is-substring(!substring)
    , !string
    )

strategies  

  string-tokenize-test =
    apply-test(!"tokenize-test1"
      , <string-tokenize> ([], <id>)
      , !"This should be one token"
      , !["This should be one token"])
  ; apply-test(!"tokenize-test2"
      , <string-tokenize> ([' '], <id>)
      , !"   This should not   be one token  "
      , !["This", "should", "not", "be", "one", "token"])
  ; apply-test(!"tokenize-test3"
      , <string-tokenize> ([' ', '.'], <id>)
      , !"   This should not   be one token  . "
      , !["This", "should", "not", "be", "one", "token"])
  ; apply-test(!"tokenize-test4"
      , <string-tokenize> ([' ', '.'], <id>)
      , !""
      , ![])
  ; apply-test(!"tokenize-test5"
      , <string-tokenize> ([' ', '.'], <id>)
      , !"    "
      , ![])

  padd-with-test =
    apply-test(!"padd-with-test",padd-with(!48),!("42",4),!"0042")

  copy-char-test =
    apply-test(!"copy-char-test", copy-char,
  !(3, 32),!"   ")
  
strategies  

   string-sort-test =
     apply-test(!"string-sort-test-a"
  , string-sort
  , !["De", "db", "Cb", "ac"]
  , !["ac", "Cb", "db", "De"]
  );
     apply-test(!"string-sort-test-b"
  , string-sort
  , !["2001", "2000", "1999", "1998"]
  , !["1998","1999","2000","2001"]
  );
     apply-test(!"string-sort-test-c"
  , string-sort-desc
  , !["2001", "2000", "1999", "1998"]
  , !["2001","2000","1999","1998"]
  )

  string-replace-test = id
    ; apply-test(!"string-replace-test-a"
      , string-replace(|"foo","bar")
      , !"foobarfoo"
      , !"barbarbar"
      )
    ; apply-test(!"string-replace-test-b"
      , string-replace(|"","bar")
      , !"foobarfoo"
      , !"foobarfoo"
      )

    ; apply-test(!"string-replace-test-c"
      , string-replace(|"foo","")
      , !"foobarfoo"
      , !"bar"
    )

    ; apply-test(!"string-replace-test-d"
      , string-replace(|"foo","bar")
      , !"fooXfoo"
      , !"barXbar"
    )

    ; apply-test(!"string-replace-test-e"
      , string-replace(|"foo","bar")
      , !"fredXfoo"
      , !"fredXbar"
    )

    ; apply-test(!"string-replace-test-f"
      , string-replace(|"foo","bar")
      , !"fooXfred"
      , !"barXfred"
    )

    ; apply-test(!"string-replace-test-g"
      , string-replace(|"foo","bar")
      , !"foofoo"
      , !"barbar"
    )

    ; apply-test(!"string-replace-test-h"
      , string-replace(|"foo","bar")
      , !"fredfoo"
      , !"fredbar"
    )

    ; apply-test(!"string-replace-test-i"
      , string-replace(|"foo","bar")
      , !"foofred"
      , !"barfred"
    )

    ; apply-test(!"string-replace-test-j"
      , string-replace(|"foo","bar")
      , !"foo"
      , !"bar"
    )
