diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 0000000..80d68e0 --- /dev/null +++ b/.gitmodules @@ -0,0 +1,3 @@ +[submodule "tests/lib/luaunit"] + path = tests/lib/luaunit + url = git@github.com:bluebird75/luaunit.git diff --git a/src/b2ws-plugin/b2ws_snippet.lua b/src/b2ws-plugin/b2ws_snippet.lua new file mode 100644 index 0000000..5ee575a --- /dev/null +++ b/src/b2ws-plugin/b2ws_snippet.lua @@ -0,0 +1,87 @@ +require "b2ws_const" +local loaded_b2ws_util= assert(loadfile(b2ws_const.B2WS_PLUGIN_PATH .. b2ws_const.B2WS_UTIL_FILE)) +loaded_b2ws_util() + +function b2ws_create_field_object(name, type, type_suffix) + local trim_type = b2ws_trim(type) + local trim_type_suffix = b2ws_trim(type_suffix) + local ws_type_name = b2ws_trim(string.match(trim_type, "(%w+)")) + local size_string = b2ws_trim(string.match(ws_type_name, "(%d+)")) + local bit_size = tonumber(size_string) + local array_number = b2ws_trim(string.match(trim_type_suffix, "%[(.*)%]")) + local bit_mask = nil + if array_number ~= nil then + if array_number == "" then + bit_size = 0 + else + local array_number_value = tonumber(array_number) + if array_number_value ~= nil then + bit_size = bit_size * array_number_value + end + end + else + local bit_start, bit_end = string.match(trim_type_suffix, ":(%d+)-(%d+)") + if bit_start ~= nil and bit_end ~= nil then + local bit_start_value = tonumber(bit_start) + local bit_end_value = tonumber(bit_end) + if bit_start ~= nil and bit_end ~= nil then + bit_size = bit_end_value - bit_start_value + 1 + bit_mask = 0 + for i = bit_start_value,bit_end_value do + bit_mask = bit_mask + 2^i + end + end + end + end + return {["name"] = b2ws_trim(name), ["type"] = ws_type_name, ["bit_size"] = bit_size, ["bit_mask"] = bit_mask, ["offset"] = 0, ["array_number"] = array_number} +end + +function b2ws_create_struct_object(name) + return {["name"] = b2ws_trim(name), ["size"] = -1, ["fields"] = {}} +end + +function b2ws_parse_struct(struct_string) + local struct_name, field_list = string.match(b2ws_trim(struct_string), "struct%s+(%g+)%s*{(.*)}") + struct_object = b2ws_create_struct_object(struct_name) + for key_index, field_string in next, b2ws_string_split(field_list, ";") + do + local trim_filed_string = b2ws_trim(field_string) + if trim_filed_string ~= "" then + local type_name, field_name, type_suffix = string.match(trim_filed_string, "(%g+)%s+([%w_]+)(%g*)") + if type_suffix == nil then + type_suffix = "" + end + struct_object.fields[key_index] = b2ws_create_field_object(field_name, type_name, type_suffix) + end + end + return struct_object +end + +proto_template = [[-- {struct_name} Layer +{struct_name}_layer = Proto("{struct_name}_layer", "{struct_name} layer") +local {struct_name}_layer_fields = {struct_name}_layer.fields +{field_declarations} +function {struct_name}_layer.dissector(buffer, packet_info, tree) + {struct_name}_layer_tree = tree:add({struct_name}_layer, buffer(0, {struct_size})) + {field_definitions} +end]] + +field_declaration_template = [===[{struct_name}_layer_fields.{field_name} = ProtoField.{fiel_type}("{struct_name}_layer_fields.{field_name}", "{field_name}", {base_type}, nil--[[valuestring]], {bit_mask}, {field_name} description})]===] +field_definition_template = [[ +local {field_name}_value = buffer({field_start},{field_end}):{to_method}() +{struct_name}_layer_tree:add({struct_name}_layer_fields.{field_name}, buffer({field_start}, {field_end}), {field_name}_value)]] + + +function b2ws_create_dissector_fields_snippet(struct_object, template_string) + return template_string +end + +function b2ws_create_dissector_layer_snippet(struct_object, template_string) + local result_template = template_string:gsub("{struct_name}", struct_object.name) + return result_template:gsub("{struct_size}", struct_object.size) +end + +function b2ws_create_dissector_snippet(struct_object) + local result_template = b2ws_create_dissector_fields_snippet(struct_object, proto_template) + return b2ws_create_dissector_layer_snippet(struct_object, result_template) +end diff --git a/src/b2ws-plugin/b2ws_util.lua b/src/b2ws-plugin/b2ws_util.lua index 800daab..7c07172 100644 --- a/src/b2ws-plugin/b2ws_util.lua +++ b/src/b2ws-plugin/b2ws_util.lua @@ -5,8 +5,32 @@ end -- from http://lua-users.org/wiki/StringTrim function b2ws_trim(s) - local from = s:match"^%s*()" - return from > #s and "" or s:match(".*%S", from) + if s == nil then + return nil + end + + local from = s:match"^%s*()" + return from > #s and "" or s:match(".*%S", from) +end + +-- from http://lua-users.org/wiki/SplitJoin +function b2ws_string_split(str, pat) + local t = {} + local fpat = "(.-)" .. pat + local last_end = 1 + local s, e, cap = str:find(fpat, 1) + while s do + if s ~= 1 or cap ~= "" then + table.insert(t,cap) + end + last_end = e+1 + s, e, cap = str:find(fpat, last_end) + end + if last_end <= #str then + cap = str:sub(last_end) + table.insert(t, cap) + end + return t end function create_b2ws_folder_file_path(plugin_path, plugin_config_file_name) diff --git a/tests/lib/luaunit b/tests/lib/luaunit new file mode 160000 index 0000000..5266555 --- /dev/null +++ b/tests/lib/luaunit @@ -0,0 +1 @@ +Subproject commit 5266555bd8bf3017593a5948f7206312158a2865 diff --git a/tests/src/luaunit.lua b/tests/src/luaunit.lua new file mode 120000 index 0000000..11558a0 --- /dev/null +++ b/tests/src/luaunit.lua @@ -0,0 +1 @@ +../lib/luaunit/luaunit.lua \ No newline at end of file diff --git a/tests/src/test_b2ws_snippet.lua b/tests/src/test_b2ws_snippet.lua new file mode 100644 index 0000000..7017522 --- /dev/null +++ b/tests/src/test_b2ws_snippet.lua @@ -0,0 +1,140 @@ + +local loaded_const_code = assert(loadfile("../../src/b2ws-plugin/b2ws_const.lua")) +loaded_const_code() +b2ws_const.B2WS_PLUGIN_PATH="../../src/b2ws-plugin/" +local loaded_test_code = assert(loadfile("../../src/b2ws-plugin/b2ws_snippet.lua")) +loaded_test_code() + +-- Unit testing starts + +local lu = require('luaunit') + +TestSnippet = {} --class + function TestSnippet:testCreateObjects() + local fieldObject = b2ws_create_field_object("foo ", " bar", "") + lu.assertEquals(fieldObject.name, 'foo') + lu.assertEquals(fieldObject.type, 'bar') + lu.assertEquals(fieldObject.bit_size, nil) + lu.assertEquals(fieldObject.bit_mask, nil) + lu.assertEquals(fieldObject.offset, 0) + lu.assertEquals(fieldObject.array_number, nil) + + local structObject = b2ws_create_struct_object("bla ") + structObject.fields[1] = fieldObject + lu.assertEquals(structObject.name, 'bla') + lu.assertEquals(structObject.size, -1) + lu.assertEquals(structObject.fields[1].name, 'foo') + lu.assertEquals(structObject.fields[1].type, 'bar') + + fieldObject = b2ws_create_field_object("foo2", "uint8_t", "") + lu.assertEquals(fieldObject.name, 'foo2') + lu.assertEquals(fieldObject.type, 'uint8') + lu.assertEquals(fieldObject.bit_size, 8) + lu.assertEquals(fieldObject.bit_mask, nil) + lu.assertEquals(fieldObject.offset, 0) + lu.assertEquals(fieldObject.array_number, nil) + + fieldObject = b2ws_create_field_object("foo3", "uint16", "[ ]") + lu.assertEquals(fieldObject.name, 'foo3') + lu.assertEquals(fieldObject.type, 'uint16') + lu.assertEquals(fieldObject.bit_size, 0) + lu.assertEquals(fieldObject.bit_mask, nil) + lu.assertEquals(fieldObject.offset, 0) + lu.assertEquals(fieldObject.array_number, "") + + fieldObject = b2ws_create_field_object("foo3-1", "uint16", "[]") + lu.assertEquals(fieldObject.name, 'foo3-1') + lu.assertEquals(fieldObject.type, 'uint16') + lu.assertEquals(fieldObject.bit_size, 0) + lu.assertEquals(fieldObject.bit_mask, nil) + lu.assertEquals(fieldObject.offset, 0) + lu.assertEquals(fieldObject.array_number, "") + + fieldObject = b2ws_create_field_object("foo4", "int16", "[3]") + lu.assertEquals(fieldObject.name, 'foo4') + lu.assertEquals(fieldObject.type, 'int16') + lu.assertEquals(fieldObject.bit_size, 48) + lu.assertEquals(fieldObject.bit_mask, nil) + lu.assertEquals(fieldObject.offset, 0) + lu.assertEquals(fieldObject.array_number, "3") + + fieldObject = b2ws_create_field_object("foo5", "int16", "[foo]") + lu.assertEquals(fieldObject.name, 'foo5') + lu.assertEquals(fieldObject.type, 'int16') + lu.assertEquals(fieldObject.bit_size, 16) + lu.assertEquals(fieldObject.bit_mask, nil) + lu.assertEquals(fieldObject.offset, 0) + lu.assertEquals(fieldObject.array_number, "foo") + + fieldObject = b2ws_create_field_object("foo6", "uint32", ":0-15") + lu.assertEquals(fieldObject.name, 'foo6') + lu.assertEquals(fieldObject.type, 'uint32') + lu.assertEquals(fieldObject.bit_size, 16) + lu.assertEquals(fieldObject.bit_mask, 0x0000ffff) + lu.assertEquals(fieldObject.offset, 0) + lu.assertEquals(fieldObject.array_number, nil) + + fieldObject = b2ws_create_field_object("foo6-1", "uint32", ":8-23") + lu.assertEquals(fieldObject.name, 'foo6-1') + lu.assertEquals(fieldObject.type, 'uint32') + lu.assertEquals(fieldObject.bit_size, 16) + lu.assertEquals(fieldObject.bit_mask, 0x00ffff00) + lu.assertEquals(fieldObject.offset, 0) + lu.assertEquals(fieldObject.array_number, nil) + + fieldObject = b2ws_create_field_object("foo6-2", "uint32", ":24-31") + lu.assertEquals(fieldObject.name, 'foo6-2') + lu.assertEquals(fieldObject.type, 'uint32') + lu.assertEquals(fieldObject.bit_size, 8) + lu.assertEquals(fieldObject.bit_mask, 0xff000000) + lu.assertEquals(fieldObject.offset, 0) + lu.assertEquals(fieldObject.array_number, nil) + + end + + function TestSnippet:testParseStruct() + local structObject = b2ws_parse_struct([[" struct foo + { uint8 bla_count; uint16_t bla[bla_count]; + uint32_t foo:0-15; int64_t bar[]; int8_t bla[3]; + int16_t bla; int32_t bla; int64_t bla; + } "]]) + lu.assertEquals(structObject.name, 'foo') + lu.assertEquals(structObject.size, -1) + lu.assertEquals(structObject.fields[1].name, 'bla_count') + lu.assertEquals(structObject.fields[1].type, 'uint8') + lu.assertEquals(structObject.fields[2].name, 'bla') + lu.assertEquals(structObject.fields[2].type, 'uint16') + lu.assertEquals(structObject.fields[3].name, 'foo') + lu.assertEquals(structObject.fields[3].type, 'uint32') + lu.assertEquals(structObject.fields[4].name, 'bar') + lu.assertEquals(structObject.fields[4].type, 'int64') + lu.assertEquals(structObject.fields[#structObject.fields].name, 'bla') + lu.assertEquals(structObject.fields[#structObject.fields].type, 'int64') + end + + function TestSnippet:testCreateSnippets() + local structObject = b2ws_parse_struct([[" struct foo + { uint8 bla_count; uint16_t bla[bla_count]; + uint32_t foo:0-15; int64_t bar[]; int8_t bla[3]; + int16_t bla; int32_t bla; int64_t bla; + } "]]) + result_template = b2ws_create_dissector_snippet(structObject) + --print(result_template) + end + + function TestSnippet:testCreateLayerSnippets() + local structObject = b2ws_parse_struct([[" struct foo + { uint8 bla_count; uint16_t bla[bla_count]; + uint32_t foo:0-15; int64_t bar[]; int8_t bla[3]; + int16_t bla; int32_t bla; int64_t bla; + } "]]) + result_template = b2ws_create_dissector_layer_snippet(structObject, "{struct_size}bla \n\t{struct_name}_bar{struct_size}\n{struct_name}:{struct_name}{struct_size}") + lu.assertEquals(result_template, "-1bla \n\tfoo_bar-1\nfoo:foo-1") + end + + +-- class TestSnippet + +local runner = lu.LuaUnit.new() +runner:setOutputType("tap") +os.exit( runner:runSuite() )