Skip to content

Commit

Permalink
cause of my arrogance, i ignored testing some functions. So i raised …
Browse files Browse the repository at this point in the history
…a lot of issues. Now i fixed it
  • Loading branch information
ulfa committed Apr 11, 2011
1 parent 7a6f94c commit ed6cdd5
Show file tree
Hide file tree
Showing 9 changed files with 137 additions and 84 deletions.
7 changes: 7 additions & 0 deletions data/xml_caps_iphone_request.xml
@@ -0,0 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<query type="iPhone OS">
<capabilities>
<capability name="brand_name" value="Apple" operator="="/>
<capability name="model_name" value="iPad" operator="="/>
</capabilities>
</query>
1 change: 1 addition & 0 deletions include/wurfler.hrl
@@ -1,6 +1,7 @@
-define(DEFAULT_TIMESTAMP, "01.01.1970").
-define(LOCATION, "Location").
-define(HOST, "host").
-define(DEBUG(Count, Value), io:format(Count ++ "... ~p~n", [Value])).
-record(capability, {name, value}).
-record(group, {id, capabilites=[]}).
-record(device, {id, user_agent=[], actual_device_root=false, fall_back=[],
Expand Down
1 change: 0 additions & 1 deletion priv/dispatch.conf
@@ -1,7 +1,6 @@
{["device", device, '*'], device_resource, []}.
{["device", '*'], device_resource, []}.
{["devices", '*'], devices_resource, []}.
{["model", model, '*'], devices_resource, []}.
{["brand", brand, '*'], brand_resource, []}.
{["brands", '*'], brands_resource, []}.
{["images", '*'], static_resource, ["priv/www/lib/images"]}.
Expand Down
8 changes: 1 addition & 7 deletions src/device_resource.erl
Expand Up @@ -29,7 +29,7 @@
%%
-export([init/1, to_xml/2, to_html/2, content_types_provided/2, resource_exists/2,
delete_resource/2, delete_completed/2, allowed_methods/2, generate_etag/2,
allow_missing_post/2, create_path/2]).
allow_missing_post/2]).
-export([post_is_create/2, process_post/2]).
-compile([export_all]).
-include_lib("../deps/webmachine/include/webmachine.hrl").
Expand Down Expand Up @@ -65,7 +65,6 @@ to_xml(ReqData, #context{device = Device} = Context) ->
resource_exists(ReqData, Context) ->
Device = wrq:path_info(device, ReqData),
Group = get_group(ReqData),
error_logger:info_msg("0.. ~p : ~p~n",[Device, Group]),
process_request(Device, Group, ReqData, Context).

get_group(ReqData) ->
Expand All @@ -74,11 +73,6 @@ get_group(ReqData) ->
_ -> "product_info"
end.

create_path(ReqData, Context) ->
LOC = "http://" ++ wrq:get_req_header("host", ReqData) ++"/device/111",
ReqData1 = wrq:set_resp_header("Location", LOC, ReqData),
{LOC, ReqData1, Context}.

process_post(ReqData, Context) ->
ReqData1 = redirect("/brands", ReqData),
delete_resource(ReqData1, Context).
Expand Down
3 changes: 1 addition & 2 deletions src/devices_resource.erl
Expand Up @@ -46,7 +46,7 @@ content_types_provided(ReqData, Context) ->


allowed_methods(ReqData, Context) ->
{['POST', 'GET'], ReqData, Context}.
{['POST'], ReqData, Context}.


to_xml(ReqData, #context{devices=Devices}=Context)->
Expand Down Expand Up @@ -76,7 +76,6 @@ process_post(ReqData, Context) ->
Type = get_type(Body),
Timestamp = get_timestamp(Body),
Devices = get_devices(Caps, Timestamp, Type),
%%save_caps_devices(Caps, Devices, Key),
D = xml_factory:to_xml(xml_factory:create_devices(insertURI(devices, ReqData, Devices))),
{true, wrq:append_to_response_body(D, ReqData), Context}.
%%
Expand Down
2 changes: 2 additions & 0 deletions src/wurfler.erl
Expand Up @@ -54,6 +54,8 @@ import_wurfl(Filename) ->
gen_server:cast(?MODULE, {import_wurfl, Filename}).
searchByCapabilities(Capabilities, Timestamp, Type) ->
gen_server:call(?MODULE, {search_by_capabilities, Capabilities, Timestamp, Type}, ?TIMEOUT).
searchByUA(undefined)->
[];
searchByUA(UserAgent)->
gen_server:call(?MODULE, {search_by_ua, UserAgent}, ?TIMEOUT).
getDeviceById(Device_Id) ->
Expand Down
18 changes: 11 additions & 7 deletions src/wurfler_db.erl
Expand Up @@ -35,7 +35,7 @@
-export([clear_capabilities_devices/0, find_devices_by_brand/2, find_capabilities_device_by_key/1]).
-export([delete_device/1, delete_brand/1, save_changed_caps_devices/1, find_changed_caps_devices/1]).
-export([get_all_cap_key/1, find_id_by_fall_back/2, find_os_device_id/1, save_os_device_id/1]).
-export([find_group_of_device/3, get_keys/1, get_all_group_names/0, find_list_of_devices/2]).
-export([find_group_of_device/3, get_keys/1, get_all_group_names/0, find_list_of_devices/2, find_list_of_devices_with_generic/2]).
-export([lookup/1, delete/2, clear/0, put/2]).
%% --------------------------------------------------------------------
%%% Internal functions
Expand All @@ -48,7 +48,7 @@ create_db() ->
_ -> error_logger:info_msg("schema created ~n")
end,
application:start(mnesia),
mnesia:create_table(devicesTbl,[{type, set},{index, [user_agent,fall_back, actual_device_root]},
mnesia:create_table(devicesTbl,[{type, set},{index, [user_agent,fall_back, actual_device_root, groups, lastmodified]},
{record_name, device},{disc_copies, [node()]}, {attributes, record_info(fields, device)}]),
mnesia:create_table(new_devicesTbl,[{type, set},{index, [user_agent,fall_back, actual_device_root]},
{record_name, device},{disc_copies, [node()]}, {attributes, record_info(fields, device)}]),
Expand Down Expand Up @@ -92,14 +92,19 @@ save_os_device_id(Os_Device_Id) ->
find_record_by_id(devicesTbl, Id) ->
mnesia:dirty_read(devicesTbl, Id).

find_list_of_devices(devicesTbl, []) ->
[];
find_list_of_devices(devicesTbl, Id) ->
find_list_of_devices(devicesTbl, Id, []).
find_list_of_devices(devicesTbl, "root", Acc) ->
find_list_of_devices(devicesTbl, "generic", Acc) ->
Acc;
find_list_of_devices(devicesTbl, Id, Acc) ->
[Device] = find_record_by_id(devicesTbl, Id),
find_list_of_devices(devicesTbl, Device#device.fall_back, [Device#device.id|Acc]).

find_list_of_devices_with_generic(devicesTbl, Id) ->
["generic"|find_list_of_devices(devicesTbl, Id)].


find_groups_by_id(devicesTbl, Id) ->
[Device] = find_record_by_id(devicesTbl, Id),
Expand All @@ -111,9 +116,8 @@ find_group_of_device(devicesTbl, Device_Id, Group_Name) ->

find_capabilities_by_id(devicesTbl, Id) ->
case find_record_by_id(devicesTbl, Id) of
[Device] -> Caps = lists:append(lists:foldl(fun(Group,Result) -> [Group#group.capabilites|Result] end, [], Device#device.groups)),
{Device#device.fall_back, Caps};
[] -> {[], []}
[Device] -> lists:append(lists:foldl(fun(Group,Result) -> [Group#group.capabilites|Result] end, [], Device#device.groups));
[] -> []
end.

find_record_by_ua(devicesTbl, Ua) ->
Expand Down Expand Up @@ -229,7 +233,7 @@ wurfler_db_test_() ->
[
?_assertEqual(2,erlang:length(get_all_keys(devicesTbl, "01.01.2010"))),
?_assertEqual(0,erlang:length(get_all_keys(devicesTbl, "01.01.2099"))),
?_assertMatch({"root", _}, find_capabilities_by_id(devicesTbl, "generic")),
?_assertMatch([], find_capabilities_by_id(devicesTbl, "generic")),
?_assertMatch([{device, "htc_desire_a8181_ver1_sub2_2",_,_,_,_,_,_,_,_,_}], find_record_by_id(devicesTbl, "htc_desire_a8181_ver1_sub2_2")),
?_assertMatch([{device, _Id,"Mozilla/5.0 (Linux; U; Android 2.1-update1; en-au; GT-I9000T Build/ECLAIR) AppleWebKit/530.17 (KHTML, like Gecko) Version/4.0 Mobile Safari/530.17", _,_,_,_,_,_,_,_}],
find_record_by_ua(devicesTbl, "Mozilla/5.0 (Linux; U; Android 2.1-update1; en-au; GT-I9000T Build/ECLAIR) AppleWebKit/530.17 (KHTML, like Gecko) Version/4.0 Mobile Safari/530.17")),
Expand Down
152 changes: 102 additions & 50 deletions src/wurfler_search.erl
Expand Up @@ -34,7 +34,7 @@
-export([init/1, handle_call/3, handle_cast/2, handle_info/2, terminate/2, code_change/3]).
-export([start_link/0, start/0]).
-export([searchByUA/2, searchByCapabilities/3, check_device/3, searchByDeviceId/1]).
-export([getAllCapabilities/1, get_all_groups/1]).
-export([getAllCapabilities/1, get_capability/2, get_all_groups/1]).
-define(TIMEOUT, infinity).

%% ====================================================================
Expand Down Expand Up @@ -101,7 +101,7 @@ handle_call({check_device, Capabilities, Key, Id}, _From, _State) ->
Result = check_device(Capabilities, Key, Id, new_state()),
{reply, Result, new_state()};
handle_call({get_all_capabilities, Device_Id}, _From, State) ->
Result = get_all_capabilities(Device_Id),
Result = get_all_capabilities(wurfler_db:find_list_of_devices_with_generic(devicesTbl, Device_Id)),
{reply, Result, State}.

%% --------------------------------------------------------------------
Expand Down Expand Up @@ -146,34 +146,49 @@ code_change(_OldVsn, State, _Extra) ->
new_state() ->
#state{devices=[], groups=[], capabilities=[]}.

search_by_capabilities(Capabilities, Timestamp, [], _State) ->
List_Of_Funs = create_funs_from_list(Capabilities),
Keys = get_keys([], Timestamp),
pmap(List_Of_Funs, Capabilities, wurfler_util:split_list(Keys, erlang:system_info(schedulers)));
%%get_devices_for_caps(List_Of_Funs, Keys, #state{capabilities=extract_only_need_capabilities(get_generic_capabilities(), Capabilities)});
search_by_capabilities(Capabilities, Timestamp, Type, _State) ->
List_Of_Funs = create_funs_from_list(Capabilities),
Keys = get_keys(Type, Timestamp),
pmap(List_Of_Funs, Capabilities, wurfler_util:split_list(Keys, erlang:system_info(schedulers))).
%%get_devices_for_caps(List_Of_Funs, Keys, State#state{capabilities=extract_only_need_capabilities(get_generic_capabilities(), Capabilities)}).

get_keys([], Timestamp) ->
wurfler_db:get_all_keys(devicesTbl, Timestamp);
get_keys(Type, _Timestamp) ->
[#os_device_id{device_ids=Device_Ids}]=wurfler_db:find_os_device_id(Type),
Device_Ids.

case wurfler_db:find_os_device_id(Type) of
[#os_device_id{device_ids=Device_Ids}] -> Device_Ids;
[] -> []
end.

pmap(_List_Of_Funs, _Capabilities, []) ->
xml_factory:create_devices([]);
pmap(List_Of_Funs, Capabilities, Keys) ->
Parent = self(),
Pids = lists:map(fun(Key) ->
proc_lib:spawn_link(fun() -> do_it(Parent, List_Of_Funs, Capabilities, Key) end)
end, Keys),
xml_factory:create_devices(gather(Pids)).
xml_factory:create_devices(gather(Pids, [])).

do_it(Parent, List_Of_Funs, Capabilities, Keys) ->
Parent ! {get_devices_for_caps(List_Of_Funs, Keys, #state{capabilities=extract_only_need_capabilities(get_generic_capabilities(), Capabilities)})}.

gather([_Pid|Pids]) ->
gather([Pid|Pids], Acc) ->
receive
{Devices} -> lists:append(Devices,gather(Pids))
{[]} -> gather(Pids, Acc);
{Devices} -> gather(Pids, lists:append(Devices,Acc))
end;
gather([]) ->
[].
gather([], Acc) ->
Acc.

search_by_device_id_only(Device_Id)->
case wurfler_db:find_record_by_id(devicesTbl, Device_Id) of
[] -> [];
[Device] -> Device
end.

search_by_device_id(Device_Id)->
case wurfler_db:find_record_by_id(devicesTbl, Device_Id) of
Expand Down Expand Up @@ -204,7 +219,7 @@ check_device(Capabilities, Key, DeviceId, State) ->
end.

get_all_groups(Device_Id) ->
List_of_devices = wurfler_db:find_list_of_devices(devicesTbl, Device_Id),
List_of_devices = wurfler_db:find_list_of_devices_with_generic(devicesTbl, Device_Id),
get_all_groups(List_of_devices, #state{groups=[]}).
get_all_groups([], #state{groups=Groups}) ->
lists:keysort(2, Groups);
Expand Down Expand Up @@ -234,37 +249,30 @@ check_capabilities(AllCapabilities, [Capability|Capabilities]) ->
end,
check_capabilities(AllCapabilities1, Capabilities).

get_all_capabilities(Device_Id) ->
{ok, #state{capabilities=Caps}} = get_all_capabilities(Device_Id, #state{capabilities=get_generic_capabilities()}),
Caps.
get_all_capabilities([], #state{capabilities=Caps}) ->
{ok, #state{capabilities=Caps}};
get_all_capabilities("root", #state{capabilities=Caps}) ->
{ok, #state{capabilities=Caps}};
get_all_capabilities("generic", #state{capabilities=Caps}) ->
{ok, #state{capabilities=Caps}};
get_all_capabilities(Device_Id, #state{capabilities=Caps}) ->
{Fall_back, Capabilities} = wurfler_db:find_capabilities_by_id(devicesTbl, Device_Id),
get_all_capabilities(Fall_back, #state{capabilities=overwrite(capabilities,Caps, Capabilities)}).

get_all_capabilities(List_Of_Fall_Back) ->
get_all_capabilities(List_Of_Fall_Back, []).

get_all_capabilities([], Acc) ->
Acc;
get_all_capabilities([Fall_Back|List_Of_Fall_Back], Acc) ->
Capabilities = wurfler_db:find_capabilities_by_id (devicesTbl, Fall_Back),
get_all_capabilities(List_Of_Fall_Back, overwrite(capabilities, Capabilities, Acc)).

get_generic_capabilities() ->
{_Fall_back, Generic} = wurfler_db:find_capabilities_by_id(devicesTbl, "generic"),
Generic.
wurfler_db:find_capabilities_by_id(devicesTbl, "generic").

add_device_to_devices(Device, State) ->
State#state{devices=[xml_factory:create_device(Device)|State#state.devices]}.

get_devices_for_caps([], _Keys, State) ->
State#state.devices;

get_devices_for_caps(_List_Of_Funs, [], State) ->
State#state.devices;

get_devices_for_caps(List_Of_Funs, [Key|Keys], State)->
Device = search_by_device_id(Key),
{ok, #state{capabilities=Caps}} = get_all_capabilities(Device#device.id, State),
get_devices_for_caps(List_Of_Funs, [Key|Keys], #state{capabilities=Needed_Caps}=State)->
Caps = get_all_capabilities(wurfler_db:find_list_of_devices(devicesTbl, Key), Needed_Caps),
case run_funs_against_list(List_Of_Funs, Caps, {nok}) of
{ok} -> get_devices_for_caps(List_Of_Funs, Keys, add_device_to_devices(Device, State));
{ok} -> get_devices_for_caps(List_Of_Funs, Keys, add_device_to_devices(search_by_device_id_only(Key), State));
{nok} -> get_devices_for_caps(List_Of_Funs, Keys, State)
end.

Expand All @@ -286,14 +294,17 @@ and_cond([Fun|Funs], {CheckName, CheckValue}, Acc) ->
and_cond([], {_CheckName, _CheckValue}, Acc) ->
Acc.

overwrite(capabilities,Generic, #capability{name=Name}=Capability) ->
lists:keyreplace(Name, 2, Generic, Capability);
overwrite(capabilities,Generic, List_Of_Capabilities) ->
overwrite(capabilities,Generic, List_Of_Capabilities, Generic).
overwrite(capabilities,_Generic, [], Acc) ->

overwrite(capability, #capability{name = Name} = Capability, Acc) ->
lists:keyreplace(Name, 2, Acc, Capability);

overwrite(capabilities, List_Of_Capabilities, []) ->
overwrite(capabilities, List_Of_Capabilities, List_Of_Capabilities);
overwrite(capabilities, [], Acc) ->
Acc;
overwrite(capabilities,Generic, [Capability|List_Of_Capabilities], Acc) ->
overwrite(capabilities,Generic, List_Of_Capabilities, overwrite(capabilities,Acc, Capability)).
overwrite(capabilities, [Capability|List_Of_Capabilities], Acc) ->
Acc1 = overwrite(capability, Capability, Acc),
overwrite(capabilities, List_Of_Capabilities, Acc1).


extract_only_need_capabilities(Generic, List_Of_Capabilities) ->
Expand All @@ -304,6 +315,9 @@ extract_one_capabilty(Generic, {Name, {_Value,_Operator}}) ->
Cap -> Cap
end.

get_capability(Capability_Name, Capabilities) ->
lists:keyfind(Capability_Name, 2, Capabilities).

create_funs_from_list(List) ->
[create_fun(Name, Value, Operator) || {Name, {Value, Operator}} <- List].

Expand Down Expand Up @@ -435,34 +449,72 @@ create_funs_from_list_test() ->
?assertEqual(3, erlang:length(create_funs_from_list(List))).

run_funs_against_list_test() ->

List_of_para=[{"jpg", {"true", '='}}, {"gif", {"true", '='}}, {"png", {"true", '='}}],
Funs = create_funs_from_list(List_of_para),
Capa_List = [#capability{name="jpg", value="true"}, #capability{name="gif", value="true"}, #capability{name="png", value="true"}],
{ok, #state{capabilities=Caps1}} = get_all_capabilities("htc_desire_a8181_ver1", #state{capabilities=Capa_List}),
?assertEqual({ok},run_funs_against_list(Funs, Caps1, [])),
Capa_List_1 = [{"jpg", {"true", '='}}, {"gif", {"true", '='}}, {"png", {"true", '='}}],
Caps1 = get_all_capabilities(["generic", "htc_desire_a8181_ver1"]),
?assertEqual({ok},run_funs_against_list(Funs, extract_only_need_capabilities(Caps1, Capa_List_1), [])),

List_of_para2=[{"jpg", {"true", '='}}, {"gif", {"true", '='}}, {"png", {"false", '='}}],
Funs2 = create_funs_from_list(List_of_para2),
Capa_List_2 = [#capability{name="jpg", value="true"}, #capability{name="gif", value="true"}, #capability{name="png", value="true"}],
{ok, #state{capabilities=Caps2}} = get_all_capabilities("htc_desire_a8181_ver1", #state{capabilities=Capa_List_2}),
?assertEqual({nok},run_funs_against_list(Funs2, Caps2, [])).
Capa_List_2 = [{"jpg", {"true", '='}}, {"gif", {"true", '='}}, {"png", {"true", '='}}],
Caps2 = get_all_capabilities(["generic", "htc_desire_a8181_ver1"]),
?assertEqual({nok},run_funs_against_list(Funs2, extract_only_need_capabilities(Caps2, Capa_List_2), [])).

search_by_capabilities_test() ->
List=[{"handheldfriendly", {"false", '='}},
{"playback_mp4", {"false", '='}},
{"playback_wmv", {"none", '='}}],
Devices = search_by_capabilities(List, "01.01.2011", [],new_state()),
%% io:format("Devices : ~p~n", [Devices]),
?assertEqual(1, erlang:length(Devices)).

overwrite_test() ->
overwrite_capability_test() ->
Generic = get_generic_capabilities(),
C = [#capability{name="device_os_version", value="3.0"}, #capability{name="device_os", value="Test"}],
?assertEqual(533,erlang:length(overwrite(capabilities,Generic, C))).
D = overwrite(capabilities, C, Generic),
Cap1 = get_capability("device_os_version", D),
Cap2 = get_capability("device_os", D),
?assertEqual("3.0", Cap1#capability.value),
?assertEqual("Test", Cap2#capability.value).

overwrite_capabilities_test() ->
Generic = wurfler_db:find_capabilities_by_id(devicesTbl, "generic"),
Acc = overwrite(capabilities, Generic, []),
Capabilities = wurfler_db:find_capabilities_by_id(devicesTbl, "apple_ipad_ver1"),
Caps = overwrite(capabilities, Capabilities, Acc),
Brand = get_capability("brand_name", Caps),
Model = get_capability("model_name", Caps),
Is_tablet = get_capability("is_tablet", Caps),
?assertEqual([], Brand#capability.value),
?assertEqual("iPad", Model#capability.value),
?assertEqual("true", Is_tablet#capability.value).

get_devices_for_caps_test() ->
List=[{"model_name", {"iPad", '='}},{"brand_name", {"Apple", '='}}],
List_Of_Funs = create_funs_from_list(List),
Keys = get_keys("iPhone OS", []),
State = #state{capabilities=extract_only_need_capabilities(get_generic_capabilities(), List)},
?assertEqual(10, erlang:length(get_devices_for_caps(List_Of_Funs, Keys, State))).

optimization_test() ->
Generic = get_generic_capabilities(),
C = [{"device_os_version", {"3.0", "="}}, {"device_os", {"Test", "="}}, {"device_os1", {"Test", ">"}}],
Result = extract_only_need_capabilities(Generic, C),
?assertEqual(2, erlang:length(Result)).
?assertEqual(2, erlang:length(Result)).

get_all_capabilities_test() ->
Caps = get_all_capabilities(["generic","generic_xhtml","apple_generic","apple_ipad_ver1"]),
Model = get_capability("model_name", Caps),
?assertEqual("iPad", Model#capability.value).












0 comments on commit ed6cdd5

Please sign in to comment.