1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215
|
----------------------------------------
-- script-name: proto.lua
-- Test the Proto/ProtoField API
----------------------------------------
------------- general test helper funcs ------------
local testlib = require("testlib")
local OTHER = "other"
-- expected number of runs per type
-- # of fields test doesn't work on Lua 5.4
local taptests = {
[OTHER]=47
}
testlib.init(taptests)
---------
-- the following are so we can use pcall (which needs a function to call)
local function callFunc(func,...)
func(...)
end
local function callObjFuncGetter(vart,varn,tobj,name,...)
vart[varn] = tobj[name](...)
end
local function setValue(tobj,name,value)
tobj[name] = value
end
local function getValue(tobj,name)
local foo = tobj[name]
end
------------- test script ------------
----------------------------------------
-- creates a Proto object, but doesn't register it yet
testlib.testing(OTHER,"Proto creation")
testlib.test(OTHER,"Proto.__call", pcall(callFunc,Proto,"foo","Foo Protocol"))
testlib.test(OTHER,"Proto.__call", pcall(callFunc,Proto,"foo1","Foo1 Protocol"))
testlib.test(OTHER,"Proto.__call", not pcall(callFunc,Proto,"","Bar Protocol"))
testlib.test(OTHER,"Proto.__call", not pcall(callFunc,Proto,nil,"Bar Protocol"))
testlib.test(OTHER,"Proto.__call", not pcall(callFunc,Proto,"bar",""))
testlib.test(OTHER,"Proto.__call", not pcall(callFunc,Proto,"bar",nil))
local dns = Proto("mydns","MyDNS Protocol")
testlib.test(OTHER,"Proto.__tostring", tostring(dns) == "Proto: MYDNS")
----------------------------------------
-- multiple ways to do the same thing: create a protocol field (but not register it yet)
-- the abbreviation should always have "<myproto>." before the specific abbreviation, to avoid collisions
testlib.testing(OTHER,"ProtoField creation")
local pfields = {} -- a table to hold fields, so we can pass them back/forth through pcall()
--- variable -- what dissector.lua did, so we almost match it
local pf_trasaction_id = 1 -- ProtoField.new("Transaction ID", "mydns.trans_id", ftypes.UINT16)
local pf_flags = 2 -- ProtoField.new("Flags", "mydns.flags", ftypes.UINT16, nil, base.HEX)
local pf_num_questions = 3 -- ProtoField.uint16("mydns.num_questions", "Number of Questions")
local pf_num_answers = 4 -- ProtoField.uint16("mydns.num_answers", "Number of Answer RRs")
local pf_num_authority_rr = 5 -- ProtoField.uint16("mydns.num_authority_rr", "Number of Authority RRs")
local pf_num_additional_rr = 6 -- ProtoField.uint16("mydns.num_additional_rr", "Number of Additional RRs")
testlib.test(OTHER,"ProtoField.new",pcall(callObjFuncGetter, pfields,pf_trasaction_id, ProtoField,"new", "Transaction ID", "mydns.trans_id", ftypes.INT16,nil,"base.DEC"))
testlib.test(OTHER,"ProtoField.new",pcall(callObjFuncGetter, pfields,pf_flags, ProtoField,"new", "Flags", "mydns.flags", ftypes.UINT16, nil, "base.HEX"))
-- tries to register a field that already exists (from the real dns proto dissector) but with incompatible type
testlib.test(OTHER,"ProtoField.new_duplicate_bad",not pcall(callObjFuncGetter, pfields,10, ProtoField,"new", "Flags", "dns.flags", ftypes.BYTES, nil, "base.NONE"))
testlib.test(OTHER,"ProtoField.bytes_duplicate_bad",not pcall(callObjFuncGetter, pfields,10, ProtoField,"bytes", "dns.id","Transaction ID"))
-- now compatible (but different type)
testlib.test(OTHER,"ProtoField.new_duplicate_ok",pcall(callObjFuncGetter, pfields,10, ProtoField,"new", "Flags", "dns.flags", ftypes.UINT32, nil, "base.HEX"))
testlib.test(OTHER,"ProtoField.uint16_duplicate_ok",pcall(callObjFuncGetter, pfields,10, ProtoField,"uint16", "dns.id","Transaction ID"))
-- invalid valuestring arg
testlib.test(OTHER,"ProtoField.new_invalid_valuestring",not pcall(callObjFuncGetter, pfields,10, ProtoField,"new", "Transaction ID", "mydns.trans_id", ftypes.INT16,"howdy","base.DEC"))
-- invalid ftype
testlib.test(OTHER,"ProtoField.new_invalid_ftype",not pcall(callObjFuncGetter, pfields,10, ProtoField,"new", "Transaction ID", "mydns.trans_id", 9999))
-- invalid description
--testlib.test(OTHER,"ProtoField.new_invalid_description",not pcall(callObjFuncGetter, pfields,10, ProtoField,"new", "", "mydns.trans_id", ftypes.INT16))
testlib.test(OTHER,"ProtoField.new_invalid_description",not pcall(callObjFuncGetter, pfields,10, ProtoField,"new", nil, "mydns.trans_id", ftypes.INT16))
testlib.test(OTHER,"ProtoField.new_invalid_abbr",not pcall(callObjFuncGetter, pfields,10, ProtoField,"new", "trans id", "", ftypes.INT16))
testlib.test(OTHER,"ProtoField.new_invalid_abbr",not pcall(callObjFuncGetter, pfields,10, ProtoField,"new", "trans id", nil, ftypes.INT16))
testlib.test(OTHER,"ProtoField.int16",pcall(callObjFuncGetter, pfields,pf_num_questions, ProtoField,"int16", "mydns.num_questions", "Number of Questions"))
testlib.test(OTHER,"ProtoField.int16",pcall(callObjFuncGetter, pfields,pf_num_answers, ProtoField,"int16", "mydns.num_answers", "Number of Answer RRs",base.DEC))
testlib.test(OTHER,"ProtoField.int16",pcall(callObjFuncGetter, pfields,pf_num_authority_rr, ProtoField,"int16", "mydns.num_authority_rr", "Number of Authority RRs",base.DEC))
testlib.test(OTHER,"ProtoField.int16",pcall(callObjFuncGetter, pfields,pf_num_additional_rr, ProtoField,"int16", "mydns.num_additional_rr", "Number of Additional RRs"))
-- now undo the table thingy
pf_trasaction_id = pfields[pf_trasaction_id]
pf_flags = pfields[pf_flags]
pf_num_questions = pfields[pf_num_questions]
pf_num_answers = pfields[pf_num_answers]
pf_num_authority_rr = pfields[pf_num_authority_rr]
pf_num_additional_rr = pfields[pf_num_additional_rr]
-- within the flags field, we want to parse/show the bits separately
-- note the "base" argument becomes the size of the bitmask'ed field when ftypes.BOOLEAN is used
-- the "mask" argument is which bits we want to use for this field (e.g., base=16 and mask=0x8000 means we want the top bit of a 16-bit field)
-- again the following shows different ways of doing the same thing basically
local pf_flag_response = ProtoField.new("Response", "mydns.flags.response", ftypes.BOOLEAN, {"this is a response","this is a query"}, 16, 0x8000, "is the message a response?")
local pf_flag_opcode = ProtoField.new("Opcode", "mydns.flags.opcode", ftypes.UINT16, nil, base.DEC, 0x7800, "operation code")
local pf_flag_authoritative = ProtoField.new("Authoritative", "mydns.flags.authoritative", ftypes.BOOLEAN, nil, 16, 0x0400, "is the response authoritative?")
local pf_flag_truncated = ProtoField.bool("mydns.flags.truncated", "Truncated", 16, nil, 0x0200, "is the message truncated?")
local pf_flag_recursion_desired = ProtoField.bool("mydns.flags.recursion_desired", "Recursion desired", 16, {"yes","no"}, 0x0100, "do the query recursivley?")
local pf_flag_recursion_available = ProtoField.bool("mydns.flags.recursion_available", "Recursion available", 16, nil, 0x0080, "does the server support recursion?")
local pf_flag_z = ProtoField.uint16("mydns.flags.z", "World War Z - Reserved for future use", base.HEX, nil, 0x0040, "when is it the future?")
local pf_flag_authenticated = ProtoField.bool("mydns.flags.authenticated", "Authenticated", 16, {"yes","no"}, 0x0020, "did the server DNSSEC authenticate?")
local pf_flag_checking_disabled = ProtoField.bool("mydns.flags.checking_disabled", "Checking disabled", 16, nil, 0x0010)
-- no, these aren't all the DNS response codes - this is just an example
local rcodes = {
[0] = "No Error",
[1] = "Format Error",
[2] = "Server Failure",
[3] = "Non-Existent Domain",
[9] = "Server Not Authoritative for zone"
}
-- the above rcodes table is used in this next ProtoField
local pf_flag_rcode = ProtoField.uint16("mydns.flags.rcode", "Response code", base.DEC, rcodes, 0x000F)
local pf_query = ProtoField.new("Query", "mydns.query", ftypes.BYTES)
local pf_query_name = ProtoField.new("Name", "mydns.query.name", ftypes.STRING)
local pf_query_name_len = ProtoField.new("Name Length", "mydns.query.name.len", ftypes.UINT8)
local pf_query_label_count = ProtoField.new("Label Count", "mydns.query.label.count", ftypes.UINT8)
local rrtypes = { [1] = "A (IPv4 host address)", [2] = "NS (authoritative name server)", [28] = "AAAA (for geeks only)" }
local pf_query_type = ProtoField.uint16("mydns.query.type", "Type", base.DEC, rrtypes)
-- again, not all class types are listed here
local classes = {
[0] = "Reserved",
[1] = "IN (Internet)",
[2] = "The 1%",
[5] = "First class",
[6] = "Business class",
[65535] = "Cattle class"
}
local pf_query_class = ProtoField.uint16("mydns.query.class", "Class", base.DEC, classes, nil, "keep it classy folks")
testlib.testing(OTHER,"Proto functions")
----------------------------------------
-- this actually registers the ProtoFields above, into our new Protocol
-- in a real script I wouldn't do it this way; I'd build a table of fields programaticaly
-- and then set dns.fields to it, so as to avoid forgetting a field
local myfields = { pf_trasaction_id, pf_flags,
pf_num_questions, pf_num_answers, pf_num_authority_rr, pf_num_additional_rr,
pf_flag_response, pf_flag_opcode, pf_flag_authoritative,
pf_flag_truncated, pf_flag_recursion_desired, pf_flag_recursion_available,
pf_flag_z, pf_flag_authenticated, pf_flag_checking_disabled, pf_flag_rcode,
pf_query, pf_query_name, pf_query_name_len, pf_query_label_count, pf_query_type, pf_query_class }
--dns.fields = myfields
testlib.test(OTHER,"Proto.fields-set", pcall(setValue,dns,"fields",myfields))
testlib.test(OTHER,"Proto.fields-get", pcall(getValue,dns,"fields"))
-- This test doesn't work on Lua 5.4 because the # operator includes the
-- reference(s) that are the linked list of allocated and free keys,
-- starting with LUA_RIDX_LAST + 1 == 3.
-- testlib.test(OTHER,"Proto.fields-get", #dns.fields == #myfields)
local pf_foo = ProtoField.uint16("myfoo.com", "Fooishly", base.DEC, rcodes, 0x000F)
local foo = Proto("myfoo","MyFOO Protocol")
local bar = Proto("mybar","MyBAR Protocol")
testlib.test(OTHER,"Proto.fields-set", pcall(setValue,foo,"fields",pf_foo))
testlib.test(OTHER,"Proto.fields-get", #foo.fields == 1)
testlib.test(OTHER,"Proto.fields-get", foo.fields[1] == pf_foo)
testlib.test(OTHER,"Proto.fields-set", not pcall(setValue,bar,"fields","howdy"))
testlib.test(OTHER,"Proto.fields-set", not pcall(setValue,bar,"fields",nil))
testlib.test(OTHER,"Proto.fields-get", #bar.fields == 0)
testlib.test(OTHER,"Proto.name-get", foo.name == "MYFOO")
testlib.test(OTHER,"Proto.name-set", not pcall(setValue,foo,"name","howdy"))
testlib.test(OTHER,"Proto.description-get", foo.description == "MyFOO Protocol")
testlib.test(OTHER,"Proto.description-set", not pcall(setValue,foo,"description","howdy"))
testlib.test(OTHER,"Proto.prefs-get", typeof(foo.prefs) == "Prefs")
testlib.test(OTHER,"Proto.prefs-set", not pcall(setValue,foo,"prefs","howdy"))
local function dummy()
setFailed(OTHER)
error("dummy function called!")
return
end
-- can't get this because we haven't set it yet
testlib.test(OTHER,"Proto.dissector-get", not pcall(getValue,foo,"dissector"))
-- now set it
testlib.test(OTHER,"Proto.dissector-set", pcall(setValue,foo,"dissector",dummy))
testlib.test(OTHER,"Proto.dissector-set", not pcall(setValue,foo,"dissector","howdy"))
testlib.test(OTHER,"Proto.dissector-get", pcall(getValue,foo,"dissector"))
testlib.test(OTHER,"Proto.prefs_changed-set", pcall(setValue,foo,"prefs_changed",dummy))
testlib.test(OTHER,"Proto.prefs_changed-get", not pcall(getValue,foo,"prefs_changed"))
testlib.test(OTHER,"Proto.prefs_changed-set", not pcall(setValue,foo,"prefs_changed","howdy"))
local function dummy_init()
testlib.test(OTHER,"Proto.init-called",true)
end
testlib.test(OTHER,"Proto.init-set", pcall(setValue,foo,"init",dummy_init))
testlib.test(OTHER,"Proto.init-set", pcall(setValue,bar,"init",dummy_init))
testlib.test(OTHER,"Proto.init-get", not pcall(getValue,foo,"init"))
testlib.test(OTHER,"Proto.init-set", not pcall(setValue,foo,"init","howdy"))
testlib.getResults()
|