anchor.diff:  -spec end_per_testcase(TestCase :: atom(), Config :: [tuple()]) -> any().
   %% Cleanup after each test case.
   %%
  +end_per_testcase(TestCase, Config) when TestCase == eap_identity_over_diameter;
  +		TestCase == pwd_id_over_diameter; TestCase == pwd_commit_over_diameter;
  +		TestCase == pwd_confirm_over_diameter	->
  +	DClient = ?config(diameter_client, Config),
  +	ok = ocs:delete_client(DClient);
   end_per_testcase(_TestCase, Config) ->
   	Socket = ?config(socket, Config),
   	RadClient = ?config(radius_client, Config),
  
positive.code: 		when is_binary(UserName) ->
  	radius_access_request(Socket, Address, Port, NasId,
  			binary_to_list(UserName), Secret, MAC, Auth, RadId,
  			EapMsg);       
  radius_access_request(Socket, Address, Port, NasId,
  		UserName, Secret, MAC, Auth, RadId, EapMsg) ->
  	A0 = radius_attributes:new(),
  	A1 = radius_attributes:add(?UserName, UserName, A0), 
  	A2 = radius_attributes:add(?NasPort, 0, A1), 
  	A3 = radius_attributes:add(?NasIdentifier, NasId, A2), 
  	A4 = radius_attributes:add(?CallingStationId, MAC, A3), 
  	A5 = radius_attributes:add(?CalledStationId,
  			"FE-EF-DE-ED-CE-ED:TestSSID", A4),
  	A6 = radius_attributes:add(?EAPMessage, EapMsg, A5), 
  	A7 = radius_attributes:add(?MessageAuthenticator, <<0:128>>, A6), 
  	Request1 = #radius{code = ?AccessRequest, id = RadId,
        authenticator = Auth, attributes = A7},
     ReqPacket1 = radius:codec(Request1),
     MsgAuth1 = crypto:hmac(md5, Secret, ReqPacket1),
     A8 = radius_attributes:store(?MessageAuthenticator, MsgAuth1, A7), 
     Request2 = Request1#radius{attributes = A8}, 
     ReqPacket2 = radius:codec(Request2),
     gen_udp:send(Socket, Address, Port, ReqPacket2).
  
  send_radius_identity(Socket, Address, Port, NasId,
  		UserName, Secret, PeerId, MAC, Auth, EapId, RadId) ->
  	EapPacket  = #eap_packet{code = response, type = ?Identity,
  	identifier = EapId, data = PeerId},
  	EapMsg = ocs_eap_codec:eap_packet(EapPacket),
  	radius_access_request(Socket, Address, Port, NasId,
  			UserName, Secret, MAC, Auth, RadId, EapMsg).
  
  receive_radius_id(Socket, Address, Port, Secret, ReqAuth, RadId) ->
  	EapMsg = radius_access_challenge(Socket, Address, Port,
  			Secret, RadId, ReqAuth),
  	#eap_packet{code = request, type = ?PWD, identifier = EapId,
  			data = EapData} = ocs_eap_codec:eap_packet(EapMsg),
  	#eap_pwd{length = false, more = false, pwd_exch = id,
  			data = EapPwdData} = ocs_eap_codec:eap_pwd(EapData),
  	#eap_pwd_id{group_desc = 19, random_fun = 16#1,
  			prf = 16#1, pwd_prep = none, token = Token,
  			identity = ServerID} = ocs_eap_codec:eap_pwd_id(EapPwdData),
  	{EapId, Token, ServerID}.
  
  %% @hidden
  client_service_opts() ->
  	OriginHost = ocs:generate_password() ++ "@siscale.org",
  	OriginRealm = ocs:generate_password() ++ "@siscale.org",
  	[{'Origin-Host', OriginHost},
  		{'Origin-Realm', OriginRealm},
  		{'Vendor-Id', 10415},
  		{'Product-Name', "SigScale Test Client (auth)"},
  		{'Auth-Application-Id', [?BASE_APPLICATION_ID, ?EAP_APPLICATION_ID]},
  		{string_decode, false},
  		{application, [{alias, base_app_test},
  				{dictionary, diameter_gen_base_rfc6733},
  				{module, diameter_test_client_cb}]},
  		{application, [{alias, eap_app_test},
  				{dictionary, diameter_gen_eap_application_rfc4072},
  				{module, diameter_test_client_cb}]}].
  
  %% @doc Add a transport capability to diameter service.
  %% @hidden
  connect(SvcName, Address, Port, Transport) when is_atom(Transport) ->
  	connect(SvcName, [{connect_timer, 30000} | transport_opts(Address, Port, Transport)]).
  
  %% @hidden
  connect(SvcName, Opts)->
  	diameter:add_transport(SvcName, {connect, Opts}).
  
  %% @hidden
  transport_opts(Address, Port, Trans) when is_atom(Trans) ->
  	transport_opts1({Trans, Address, Address, Port}).
  
  %% @hidden
  transport_opts1({Trans, LocalAddr, RemAddr, RemPort}) ->
  	[{transport_module, Trans}, {transport_config,
  			[{raddr, RemAddr}, {rport, RemPort},
  			{reuseaddr, true}, {ip, LocalAddr}]}].
  
  radius_access_challenge(Socket, Address, Port, Secret, RadId, ReqAuth) ->
  	receive_radius(?AccessChallenge, Socket, Address, Port, Secret, RadId, ReqAuth).
  
negative.code: 	{ok, EapMsg} = radius_attributes:find(?EAPMessage, RespAttr1),
  	EapMsg.
  
  send_radius_identity(Socket, Address, Port, NasId,
  		UserName, Secret, PeerId, MAC, Auth, EapId, RadId) ->
  	EapPacket  = #eap_packet{code = response, type = ?Identity,
  			identifier = EapId, data = PeerId},
  	EapMsg = ocs_eap_codec:eap_packet(EapPacket),
  	radius_access_request(Socket, Address, Port, NasId,
  			UserName, Secret, MAC, Auth, RadId, EapMsg).
  
  receive_radius_id(Socket, Address, Port, Secret, ReqAuth, RadId) ->
  	EapMsg = radius_access_challenge(Socket, Address, Port,
  			Secret, RadId, ReqAuth),
  	#eap_packet{code = request, type = ?PWD, identifier = EapId,
  			data = EapData} = ocs_eap_codec:eap_packet(EapMsg),
  	#eap_pwd{length = false, more = false, pwd_exch = id,
  			data = EapPwdData} = ocs_eap_codec:eap_pwd(EapData),
  	#eap_pwd_id{group_desc = 19, random_fun = 16#1,
  			prf = 16#1, pwd_prep = none, token = Token,
  			identity = ServerID} = ocs_eap_codec:eap_pwd_id(EapPwdData),
  	{EapId, Token, ServerID}.
  
  send_radius_id(Socket, Address, Port, Secret, Auth, UserName,
  		NasId, PeerId, MAC, Token, EapId, RadId) ->
  	EapPwdId = #eap_pwd_id{group_desc = 19, random_fun = 16#1, prf = 16#1,
  			token = Token, pwd_prep = none, identity = PeerId},
  	EapPwd = #eap_pwd{pwd_exch = id, data = ocs_eap_codec:eap_pwd_id(EapPwdId)},
  	EapPacket  = #eap_packet{code = response, type = ?PWD, identifier = EapId,
  			data = ocs_eap_codec:eap_pwd(EapPwd)},
  	EapMsg = ocs_eap_codec:eap_packet(EapPacket),
  	radius_access_request(Socket, Address, Port, NasId,
  			UserName, Secret, MAC, Auth, RadId, EapMsg).
  
  receive_radius_commit(Socket, Address, Port, Secret, ReqAuth, RadId) ->
  	EapMsg = radius_access_challenge(Socket, Address, Port,
  			Secret, RadId, ReqAuth),
  	#eap_packet{code = request, type = ?PWD, identifier = EapId,
  			data = EapData} = ocs_eap_codec:eap_packet(EapMsg),
  	#eap_pwd{length = false, more = false, pwd_exch = commit,
  			data = EapPwdData} = ocs_eap_codec:eap_pwd(EapData),
  	#eap_pwd_commit{element = ElementS,
  			scalar = ScalarS} = ocs_eap_codec:eap_pwd_commit(EapPwdData),
  	{EapId, ElementS, ScalarS}.
  
  send_radius_commit(Socket, Address, Port, Secret, Auth, UserName,
  		NasId, MAC, ScalarP, ElementP, EapId, RadId) ->
  	EapPwdCommit = #eap_pwd_commit{scalar = ScalarP, element = ElementP},
  	EapPwd = #eap_pwd{length = false, more = false, pwd_exch = commit,
  			data = ocs_eap_codec:eap_pwd_commit(EapPwdCommit)},
  	EapPacket = #eap_packet{code = response, type = ?PWD,
  			identifier = EapId, data = ocs_eap_codec:eap_pwd(EapPwd)},
  	EapMsg = ocs_eap_codec:eap_packet(EapPacket),
  	radius_access_request(Socket, Address, Port, NasId,
  			UserName, Secret, MAC, Auth, RadId, EapMsg).
  
  receive_radius_confirm(Socket, Address, Port, Secret, ReqAuth, RadId) ->
  	EapMsg = radius_access_challenge(Socket, Address, Port,
  			Secret, RadId, ReqAuth),
  	#eap_packet{code = request, type = ?PWD, identifier = EapId,
  			data = EapData} = ocs_eap_codec:eap_packet(EapMsg),
  	#eap_pwd{length = false, more = false, pwd_exch = confirm,
  			data = ConfirmS} = ocs_eap_codec:eap_pwd(EapData),
  	{EapId, ConfirmS}.
  
  send_radius_confirm(Socket, Address, Port, Secret, Auth, UserName,
  		NasId, MAC, ConfirmP, EapId, RadId) ->
  	EapPwd = #eap_pwd{length = false, more = false,
  			pwd_exch = confirm, data = ConfirmP},
  	EapPacket = #eap_packet{code = response, type = ?PWD,
  			identifier = EapId, data = ocs_eap_codec:eap_pwd(EapPwd)},
  	EapMsg = ocs_eap_codec:eap_packet(EapPacket),
  	radius_access_request(Socket, Address, Port, NasId,
  			UserName, Secret, MAC, Auth, RadId, EapMsg).
  
  receive_radius_success(Socket, Address, Port, Secret, ReqAuth, RadId) ->
  	EapMsg = radius_access_accept(Socket, Address, Port,
  			Secret, RadId, ReqAuth),
  	#eap_packet{code = success,
  			identifier = EapId} = ocs_eap_codec:eap_packet(EapMsg),
  	EapId.
  
  receive_radius_failure(Socket, Address, Port, Secret, ReqAuth, RadId) ->
  	EapMsg = radius_access_reject(Socket, Address, Port,
  			Secret, RadId, ReqAuth),
  	#eap_packet{code = failure,
  			identifier = EapId} = ocs_eap_codec:eap_packet(EapMsg),
  	EapId.
  
  receive_radius_nak(Socket, Address, Port, Secret, ReqAuth, RadId) ->
  	EapMsg = radius_access_reject(Socket, Address, Port,
  			Secret, RadId, ReqAuth),
  	#eap_packet{code = response, type = ?LegacyNak, identifier = EapId,
  			data = AuthTypes} = ocs_eap_codec:eap_packet(EapMsg),
  	{EapId, AuthTypes}.
  
  %% @doc Add a transport capability to diameter service.
  %% @hidden
  connect(SvcName, Address, Port, Transport) when is_atom(Transport) ->
  	connect(SvcName, [{connect_timer, 30000} | transport_opts(Address, Port, Transport)]).
  
  %% @hidden
  connect(SvcName, Opts)->
  	diameter:add_transport(SvcName, {connect, Opts}).
  
  %% @hidden
  client_service_opts() ->
  	OriginHost = ocs:generate_password() ++ "@siscale.org",
  	OriginRealm = ocs:generate_password() ++ "@siscale.org",
  	[{'Origin-Host', OriginHost},
  		{'Origin-Realm', OriginRealm},
  		{'Vendor-Id', 10415},
  		{'Product-Name', "SigScale Test Client (auth)"},
  		{'Auth-Application-Id', [?BASE_APPLICATION_ID,
  														 ?EAP_APPLICATION_ID]},
  		{string_decode, false},
  		{application, [{alias, base_app_test},
  				{dictionary, diameter_gen_base_rfc6733},
  				{module, diameter_test_client_cb}]},
  		{application, [{alias, eap_app_test},
  				{dictionary, diameter_gen_eap_application_rfc4072},
  				{module, diameter_test_client_cb}]}].
  
  %% @hidden
  transport_opts(Address, Port, Trans) when is_atom(Trans) ->
  	transport_opts1({Trans, Address, Address, Port}).
  
  %% @hidden
  transport_opts1({Trans, LocalAddr, RemAddr, RemPort}) ->
  	[{transport_module, Trans}, {transport_config,
  			[{raddr, RemAddr}, {rport, RemPort},
  			{reuseaddr, true}, {ip, LocalAddr}]}].
  
  send_diameter_identity(SId, EapId, PeerId) ->
  	EapPacket  = #eap_packet{code = response, type = ?Identity, identifier = EapId, data = PeerId},
  	EapMsg = ocs_eap_codec:eap_packet(EapPacket),
  	DER = #diameter_eap_app_DER{'Session-Id' = SId, 'Auth-Application-Id' = ?EAP_APPLICATION_ID,
  		'Auth-Request-Type' = ?'DIAMETER_BASE_AUTH-REQUEST-TYPE_AUTHORIZE_AUTHENTICATE',
  		'EAP-Payload' = EapMsg},
  	{ok, Answer} = diameter:call(?MODULE, eap_app_test, DER, []),
  	Answer.
  
  send_diameter_id(SId, Token, PeerId, EapId) ->
  	EapPwdId = #eap_pwd_id{group_desc = 19, random_fun = 16#1, prf = 16#1,
  			token = Token, pwd_prep = none, identity = PeerId},
  	EapPwd = #eap_pwd{pwd_exch = id, data = ocs_eap_codec:eap_pwd_id(EapPwdId)},
  	EapPacket  = #eap_packet{code = response, type = ?PWD, identifier = EapId,
  			data = ocs_eap_codec:eap_pwd(EapPwd)},
  	EapPayload = ocs_eap_codec:eap_packet(EapPacket),
  	DER = #diameter_eap_app_DER{'Session-Id' = SId, 'Auth-Application-Id' = ?EAP_APPLICATION_ID,
  		'Auth-Request-Type' = ?'DIAMETER_BASE_AUTH-REQUEST-TYPE_AUTHORIZE_AUTHENTICATE',
  		'EAP-Payload' = EapPayload},
  	{ok, Answer} = diameter:call(?MODULE, eap_app_test, DER, []),
  	Answer.
  
  send_diameter_commit(SId, ScalarP, ElementP, EapId) ->
  	EapPwdCommit = #eap_pwd_commit{scalar = ScalarP, element = ElementP},
  	EapPwd = #eap_pwd{length = false, more = false, pwd_exch = commit,
  			data = ocs_eap_codec:eap_pwd_commit(EapPwdCommit)},
  	EapPacket = #eap_packet{code = response, type = ?PWD,
  			identifier = EapId, data = ocs_eap_codec:eap_pwd(EapPwd)},
  	EapPayload = ocs_eap_codec:eap_packet(EapPacket),
  	DER = #diameter_eap_app_DER{'Session-Id' = SId, 'Auth-Application-Id' = ?EAP_APPLICATION_ID,
  		'Auth-Request-Type' = ?'DIAMETER_BASE_AUTH-REQUEST-TYPE_AUTHORIZE_AUTHENTICATE',
  		'EAP-Payload' = EapPayload},
  	{ok, Answer} = diameter:call(?MODULE, eap_app_test, DER, []),
  	Answer.
  
  send_diameter_confirm(SId, ConfirmP, EapId) ->
  	EapPwdConfirm = #eap_pwd{length = false, more = false, pwd_exch = confirm, data = ConfirmP},
  	EapPacket = #eap_packet{code = response, type = ?PWD,
  			identifier = EapId, data = ocs_eap_codec:eap_pwd(EapPwdConfirm)},
  	EapPayload = ocs_eap_codec:eap_packet(EapPacket),
  	DER = #diameter_eap_app_DER{'Session-Id' = SId, 'Auth-Application-Id' = ?EAP_APPLICATION_ID,
  		'Auth-Request-Type' = ?'DIAMETER_BASE_AUTH-REQUEST-TYPE_AUTHORIZE_AUTHENTICATE',
  		'EAP-Payload' = EapPayload},
  	{ok, Answer} = diameter:call(?MODULE, eap_app_test, DER, []),
  	Answer.
  
  %% @hidden
  price(Type, Units, Size, Amount) ->
  	#price{name = ocs:generate_identity(),
  			type = Type, units = Units,
  			size = Size, amount = Amount}.
  
  %% @hidden
  bucket(Units, RA) ->
  	#bucket{units = Units, remain_amount = RA,
  		start_date = erlang:system_time(?MILLISECOND),
  		end_date = erlang:system_time(?MILLISECOND) + 2592000000}.
  
  %% @hidden
  add_offer(Prices, Spec) when is_integer(Spec) ->
  	add_offer(Prices, integer_to_list(Spec));
  add_offer(Prices, Spec) ->
  	Offer = #offer{name = ocs:generate_identity(),
  	price = Prices, specification = Spec},
  	{ok, #offer{name = OfferId}} = ocs:add_offer(Offer),
  	OfferId.
  
  %% @hidden
  add_product(OfferId) ->
  	add_product(OfferId, []).
  add_product(OfferId, Chars) ->
  	{ok, #product{id = ProdRef}} = ocs:add_product(OfferId, Chars),
  	ProdRef.
  
  %% @hidden
  add_service(ProdRef) ->
  	{ok, Service} =
  			ocs:add_service(ocs:generate_identity(), ocs:generate_password(),
  			ProdRef, []),
  	Service.
  
  %% @hidden
  add_bucket(ProdRef, Bucket) ->
  	{ok, _, #bucket{id = BId}} = ocs:add_bucket(ProdRef, Bucket),
  	BId.
  
  