Vorlagenprogrammierung Diskussionen Lua Test Unterseiten
Modul Deutsch English

Modul: Dokumentation

Diese Seite enthält Code in der Programmiersprache Lua. Einbindungszahl Cirrus


local Export = { suite  = "JSONutil",
                 sub    = "test",
                 serial = "2019-07-17" }
--[=[
Unit test for JSONutil
=p.fiat()
]=]



local Cases = {
    { source = '{ "simple": "assignment" }' },
    { source = '{ "beg": "\\"escaped quote", "mid": "escaped\\"quote", "end": "escaped quote\\"" }' },
    { source = '{ "multiline": "Some text\nin several lines\nalso with\ttabulator" }',
      second = '{ "multiline": "Some text\\nin several lines\\nalso with\\ttabulator" }' },
    { source = '{ "lineseps": "Ux\nstyle and\rApple and MS\r\nDOS" }',
      second = '{ "lineseps": "Ux\\nstyle and\\nApple and MS\\nDOS" }' },
    { source = '{ "commented": true } // line at end',
      second = '{ "commented": true }' },
    { source = '{ "commented":// line amid\n true// second line\n } ',
      second = '{ "commented": true }' },
    { source = '{ "commented": /* middle */true }',
      second = '{ "commented": true }' },
    { source = '{ "commented":/* middle */"edge" }',
      second = '{ "commented":"edge" }' },
    { source = '{ "NoComment": "An URL http://example.org/ is not a comment" }' },
    { source = 'No JSON',
      status = 'Bracket0' },
    { source = '{ "simple": "assignment" } garbage',
      status = 'Trailing',
      second = 'garbage' },
    { source = '{ "quoting": \'apostrophes\' }',
      status = 'Qoute',
      second = "'apostrophes' }" },
    { source = '{ "missing": "qoute }',
      status = 'QouteEnd',
      second = 'qoute }' },
    { source = '{ "missing": "qoute (escaped)\\" }',
      status = 'QouteEnd',
      second = 'qoute (escaped)\\" }' },
    { source = '{ "htab": "h' .. string.char( 8 ) .. 'tab" }',
      status = 'ControlChar',
      second = 'tab" }' },
    { source = '{ "comma": "trailing", }',
      status = 'CommaEnd',
      second = ', }' },
    { source = '{ "comma": [ "trailing", ] }',
      status = 'CommaEnd',
      second = ', ] }' },
    { source = '{ "comma": true, }',
      status = 'CommaEnd',
      second = ': true, }' },
    { source = '{ "unclosed": true',
      status = 'BracketCloseLack',
      second = '}' },
    { source = '{ "unclosed": "terminating"',
      status = 'BracketCloseLack',
      second = '}' },
    { source = '{ { "unclosed": 99',
      status = 'BracketCloseLack',
      second = '2 }' },
    { source = '{ "unclosed": [ 42 }',
      status = 'BracketCloseLack',
      second = ']' },
    { source = '{ "unclosed": [ 42 ] ] }',
      status = 'BracketClosePlus',
      second = ']' },
    { source = '{ "unclosed": [ 42 ] ] ] }',
      status = 'BracketClosePlus',
      second = '2 ]' },
    { source = '{ "commented":  /* middle true }',
      status = 'CommentEnd',
      second = 'middle true }' }
}



local Codes = { { k   = 9,
                  s   = "\\t",
                  say = "Tab" },
                { k   = 10,
                  s   = "\\n",
                  say = "LF" }  ,
                { k   = 13,
                  s   = "\\r",
                  say = "CR" } }
local Frame, Slang, Utility



local function far()
    local r
    if not Slang then
        local o = mw.message.new( "lang" )
        if o:exists() then
            Slang = Frame:preprocess( "{{int:lang}}" )
        else
            local g, lucky, s, t
            Slang = true
            s = string.format( "I18n/Module:%s.tab", Export.suite )
            lucky, t = pcall( mw.ext.data.get, s, "_" )
            lucky, g = pcall( require, "Module:Multilingual" )
            if type( g ) == "table"  and
               type( g.Multilingual ) == "function"  and
               type( t ) == "table" then
                local Multilingual = g.Multilingual()
                t = t.data
                if type( t ) == "table"  and
                   type( Multilingual.userLang ) == "function" then
                    local e
                    g = { }
                    s = ""
                    for i = 1, #t do
                        e = t[ i ]
                        if type( e ) == "table"  and
                           type( e[ 1 ] ) == "string"  and
                           e[ 1 ]:find( "^err_" )  and
                           type( e[ 2 ] ) == "table" then
                            e = e[ 2 ]
                            if type( e ) == "table" then
                                for k, v in pairs( e ) do
                                    if type( k ) == "string"  and
                                       type( v ) == "string" then
                                        g[ k ] = true
                                    end
                                end   -- for k, v
                            end
                        end
                    end   -- for i
                    for k, v in pairs( g ) do
                        if s == "" then
                            s = k
                        else
                            s = string.format( "%s %s", s, k )
                        end
                    end   -- for k, v
                    Slang = Multilingual.userLang( s, Frame )
                end
            end
        end
    end
    if type( Slang ) == "string" then
        r = Slang
    end
    return r
end -- far()



local function father()
    local r
    if not Utility then
        local try = string.format( "Module:%s", Export.suite )
        local lucky
        lucky, try = pcall( require, try )
        if type( try ) == "table" then
            if type( try.JSONutil ) == "function" then
                Utility = try.JSONutil()
            else
                r = string.format( "%s bad init", Export.suite )
            end
        else
            r = try
        end
        if r then
            local e = mw.html.create( "span" )
                             :addClass( "error" )
                             :wikitext( r )
            r = tostring( e )
        end
    end
    return r
end -- father()



local function fault()
    -- Retrieve unit test result
    -- Returns string with wikisyntax
    local errors = { "Bracket0",
                     "BracketCloseLack",
                     "BracketClosePlus",
                     "CommaEnd",
                     "CommentEnd",
                     "ControlChar",
                     "Qoute",
                     "QouteEnd",
                     "Trailing" }
    local r = ""
    local s, s2
    for i = 1, #errors do
        s  = errors[ i ]
        s2 = string.format( "Trailing%d", i )
        r  = string.format( "%s\n; %s\n: %s",
                            r, s, Utility.fault( s, s2, far() ) )
    end   -- for i
    return r
end -- fault()



local function fetch()
    -- Retrieve unit test result
    -- Returns string with wikisyntax
    local r = ""
    local e, s
    for i = 1, #Cases do
        if i > 1 then
            r = r .. "\n----\n"
        end
        e = Cases[ i ]
        e = Utility.fetch( e.source, true, far() )
        s = type( e )
        if s == "string" then
            r = r .. mw.text.encode( e )
        elseif s == "table" then
            s = mw.text.jsonEncode( e, mw.text.JSON_PRETTY )
            s = mw.text.encode( s ):gsub( "\n", "<br / >" )
                                   :gsub( "://", "&#58;//" )
            e = mw.html.create( "span" )
                       :css( {["font-family"] = "monospace" } )
                       :wikitext( s )
            r = r .. tostring( e )
        else
            r = string.format( "%s%s %s", r, "fetch() BAD TYPE:", s )
        end
    end   -- for i
    return r
end -- fetch()



local function fiat()
    -- Retrieve unit test result
    -- Returns string with wikisyntax
    local scream = "style='background:red'"
    local spaced = "style='font-family:monospace'"
    local flip   = function ( apply, at, alter )
                       local xe
                       local xr = apply:gsub( "''", "&apos;&apos;" )
                       for k = 1, #Codes do
                           xe = Codes[ k ]
                           xr = xr:gsub( xe[ at ], xe[ alter ] )
                       end   -- for k
                       xr = xr:gsub( "://", "&#58;//" )
                       return xr
                   end   -- flip()
    local r      = "{| class='wikitable'\n" ..
                   "|-\n" ..
                   "! Input !! Code (fault) !! String (trailing)\n"
    local e, legal, s, score, second, show, sign
    for i = 1, #Codes do
        e = Codes[ i ]
        e.str = string.char( e.k )
        e.sup = string.format( "<sup>%s</sup>", e.say )
    end   -- for i
    for i = 1, #Cases do
        e     = Cases[ i ]
        legal = true
        score, s = Utility.fair( e.source )
        if score then
            legal = ( score == e.status )
            if not legal then
                score = string.format( "'''%s'''",
                                       e.status or "unexpected" )
            end
        elseif e.status then
            score = string.format( "&minus; %s", e.status )
            legal = false
        else
            score = "&#8211;"
        end
        if legal then
            second = e.second or e.source
            legal  = ( s == second )
        end
        if legal then
            sign = ""
        else
            sign = scream
        end
        show = flip( e.source, "str", "sup" )
        s    = flip( s, "str", "sup" )
        r = string.format( "%s|- %s\n|%s| %s\n| %s\n|%s| %s\n",
                           r, sign, spaced, show, score, spaced, s )
    end   -- for i
    r = r .. "|}"
    return r
end -- fiat()



-- Export
local p = { }

p.fault = function ( frame )
    Frame = frame
    return father() or fault()
end

p.fetch = function ( frame )
    Frame = frame
    return father() or fetch()
end

p.fiat = function ()
    return father() or fiat()
end

return p