Added the Rss tests, written by Mihai Balan

cusax-fix
Benoit Pradelle 18 years ago
parent 83b841bb40
commit 3ce23a1e74

@ -872,7 +872,7 @@
bundle-systray,bundle-browserlauncher,bundle-gibberish,
bundle-gibberish-slick,bundle-plugin-gibberishaccregwizz,
bundle-plugin-extended-callhistory-search,
bundle-rss,bundle-plugin-rssaccregwizz,
bundle-rss, bundle-rss-slick,bundle-plugin-rssaccregwizz,
bundle-zeroconf,bundle-plugin-zeroconfaccregwizz,
bundle-irc,bundle-plugin-ircaccregwizz,
bundle-pluginmanager,bundle-notification"/>
@ -1600,6 +1600,17 @@ javax.swing.event, javax.swing.border"/>
prefix="resources/images/rss"/>
</jar>
</target>
<!-- BUNDLE-RSS-SLICK -->
<!-- Creates a bundle containing the slick for the Gibberish protocol
provider.-->
<target name="bundle-rss-slick">
<jar compress="false" destfile="${bundles.dest}/protocol-rss-slick.jar"
manifest="${testsrc}/net/java/sip/communicator/slick/protocol/rss/rss.provider.slick.manifest.mf">
<zipfileset dir="${dest}/net/java/sip/communicator/slick/protocol/rss"
prefix="net/java/sip/communicator/slick/protocol/rss"/>
</jar>
</target>
<!-- BUNDLE-PLUGIN-RSSACCREGWIZZ -->
<target name="bundle-plugin-rssaccregwizz">

@ -8,6 +8,7 @@ org.osgi.framework.system.packages= org.osgi.framework; \
javax.swing.event; \
javax.swing.table; \
javax.swing.text; \
javax.imageio;\
org.w3c.dom; \
org.xml.sax; \
org.xml.sax.helpers; \
@ -61,6 +62,7 @@ felix.auto.start.4= \
file:sc-bundles/history.jar \
file:sc-bundles/protocol-icq.jar \
file:sc-bundles/smacklib.jar \
file:sc-bundles/protocol-rss.jar \
file:sc-bundles/protocol-jabber.jar \
file:sc-bundles/protocol-msn.jar \
file:sc-bundles/protocol-sip.jar \
@ -86,6 +88,7 @@ felix.auto.start.5= \
file:sc-bundles/protocol-msn-slick.jar \
file:sc-bundles/protocol-yahoo-slick.jar \
file:sc-bundles/protocol-gibberish-slick.jar \
file:sc-bundles/protocol-rss-slick.jar \
file:sc-bundles/msghistory-slick.jar \
file:sc-bundles/callhistory-slick.jar

@ -14,7 +14,8 @@ net.java.sip.communicator.slick.runner.TEST_LIST=ConfigurationServiceLick \
JabberProtocolProviderSlick \
YahooProtocolProviderSlick \
MsnProtocolProviderSlick \
GibberishProtocolProviderServiceLick
GibberishProtocolProviderServiceLick \
RssProtocolProviderServiceLick
# MediaServiceLick \

@ -69,4 +69,10 @@ public interface ProtocolNames
* The Zeroconf protcool.
*/
public static final String ZEROCONF = "Zeroconf";
/**
* The RSS protocol.
*/
public static final String RSS = "RSS";
}

@ -0,0 +1,508 @@
/*
* SIP Communicator, the OpenSource Java VoIP and Instant Messaging client.
*
* Distributable under LGPL license.
* See terms of license at gnu.org.
*/
package net.java.sip.communicator.slick.protocol.rss;
/**
* This class produces the RSS samples we use in our tests. Right now we're
* using excerpts from a real life feed, but that could change to a more
* lightweight approach.
*
* Feed components are stored as inline string to minimize overhead while
* testing.
*
* @author Mihai Balan
*/
public class FeedFactory {
/**
* String representing the header of a RSS feed.
*/
private static String rssHeader =
"<?xml version=\"1.0\" encoding=\"UTF-8\"?>"
+"<rss version=\"2.0\""
+" xmlns:content=\"http://purl.org/rss/1.0/modules/content/\""
+" xmlns:wfw=\"http://wellformedweb.org/CommentAPI/\""
+" xmlns:dc=\"http://purl.org/dc/elements/1.1/\">"
+" <channel>"
+" <title>miChou's photoblog</title>"
+" <link>http://mihaibalan.wordpress.com</link>"
+" <description>The world through my eyes</description>"
+" <pubDate>Mon, 20 Aug 2007 22:20:57 +0000</pubDate>"
+" <generator>http://wordpress.org/?v=MU</generator>"
+" <language>ro</language>";
/**
* String containing the body of a RSS feed.
*/
private static String rssBody =
" <item>"
+" <title>Milky wave</title>"
+" <link>http://mihaibalan.wordpress.com/2007/08/15/milky-wave/</link>"
+" <comments>http://mihaibalan.wordpress.com/2007/08/15/milky-wave/#co"
+"mments</comments>"
+" <pubDate>Tue, 14 Aug 2007 22:02:48 +0000</pubDate>"
+" <dc:creator>mich0u</dc:creator>"
+" <category><![CDATA[flash]]></category>"
+" <guid isPermaLink=\"false\">http://mihaibalan.wordpress.com/2007/08"
+"/15/milky-wave/</guid>"
+" <description><![CDATA["
+"]]></description>"
+" <content:encoded><![CDATA[<div class='snap_preview'><p align=\"cent"
+"er\"><a href=\"http://www.flickr.com/photos/mi-chou/1092690810/\" title="
+"\"Photo Sharing\"><img src=\"http://farm2.static.flickr.com/1419/10926908"
+"10_79510d9695.jpg\" alt=\"Milky wave\" style=\"border:medium none;\" heig"
+"ht=\"288\" width=\"500\" /></a></p>"
+"</div>]]></content:encoded>"
+" <wfw:commentRss>http://mihaibalan.wordpress.com/2007/08/15/milky-"
+"wave/feed/</wfw:commentRss>"
+" </item>"
+" <item>"
+" <title>Light patterns</title>"
+" <link>http://mihaibalan.wordpress.com/2007/08/14/light-patterns/</"
+"link>"
+" <comments>http://mihaibalan.wordpress.com/2007/08/14/light-pattern"
+"s/#comments</comments>"
+" <pubDate>Mon, 13 Aug 2007 22:02:32 +0000</pubDate>"
+" <dc:creator>mich0u</dc:creator>"
+" <category><![CDATA[dark]]></category>"
+" <category><![CDATA[architecture]]></category>"
+" <guid isPermaLink=\"false\">http://mihaibalan.wordpress.com/2007/08"
+"/14/light-patterns/</guid>"
+" <description><![CDATA["
+"]]></description>"
+" <content:encoded><![CDATA[<div class='snap_preview'><p align=\"cent"
+"er\"><a href=\"http://www.flickr.com/photos/mi-chou/1091949941/\" title="
+"\"Photo Sharing\"><img src=\"http://farm2.static.flickr.com/1055/10919499"
+"41_34853b5130.jpg\" alt=\"Light patterns\" style=\"border:medium none;\" "
+"height=\"386\" width=\"500\" /></a></p>"
+"</div>]]></content:encoded>"
+" <wfw:commentRss>http://mihaibalan.wordpress.com/2007/08/14/light-p"
+"atterns/feed/</wfw:commentRss>"
+" </item>";
/**
* String containing the updates to the RSS feed.
*/
private static String rssBodyUpdate =
" <item>"
+" <title>Tuig - The show goes on</title>"
+" <link>http://mihaibalan.wordpress.com/2007/08/17/tuig-the-show-goes"
+"-on/</link>"
+" <comments>http://mihaibalan.wordpress.com/2007/08/17/tuig-the-show"
+"-goes-on/#comments</comments>"
+" <pubDate>Thu, 16 Aug 2007 22:05:53 +0000</pubDate>"
+" <dc:creator>mich0u</dc:creator>"
+" <category><![CDATA[water]]></category>"
+" <category><![CDATA[people]]></category>"
+" <guid isPermaLink=\"false\">http://mihaibalan.wordpress.com/2007/08"
+"/17/tuig-the-show-goes-on/</guid>"
+" <description><![CDATA["
+"]]></description>"
+" <content:encoded><![CDATA[<div class='snap_preview'><p align=\"cen"
+"ter\"><a href=\"http://www.flickr.com/photos/mi-chou/1030251126/\" title="
+"\"Photo Sharing\"><img src=\"http://farm2.static.flickr.com/1361/10302511"
+"26_9a5d311039.jpg\" alt=\"Tuig - The show goes on\" style=\"border:medium"
+" none;\" height=\"340\" width=\"500\" /></a></p>"
+"</div>]]></content:encoded>"
+" <wfw:commentRss>http://mihaibalan.wordpress.com/2007/08/17/tuig-the"
+"-show-goes-on/feed/</wfw:commentRss>"
+" </item>"
+" <item>"
+" <title>Tuig - Patiently waiting</title>"
+" <link>http://mihaibalan.wordpress.com/2007/08/16/tuig-patiently-wai"
+"ting/</link>"
+" <comments>http://mihaibalan.wordpress.com/2007/08/16/tuig-patiently"
+"-waiting/#comments</comments>"
+" <pubDate>Wed, 15 Aug 2007 22:03:55 +0000</pubDate>"
+" <dc:creator>mich0u</dc:creator>"
+" <category><![CDATA[sky]]></category>"
+" <category><![CDATA[urban]]></category>"
+" <category><![CDATA[dark]]></category>"
+" <guid isPermaLink=\"false\">http://mihaibalan.wordpress.com/2007/0"
+"8/16/tuig-patiently-waiting/</guid>"
+" <description><![CDATA["
+"]]></description>"
+" <content:encoded><![CDATA[<div class='snap_preview'><p align=\"cent"
+"er\"><a href=\"http://www.flickr.com/photos/mi-chou/1030250394/\" title="
+"\"Photo Sharing\"><img src=\"http://farm2.static.flickr.com/1029/10302503"
+"94_687df58297.jpg\" alt=\"Tuig - Patiently waiting\" style=\"border:mediu"
+"m none;\" height=\"500\" width=\"410\" /></a></p>"
+"<p> <a href=\"http://mihaibalan.wordpress.com/2007/08/16/tuig-patiently-w"
+"aiting/#more-118\" class=\"more-link\">(more&#8230;)</a></p>"
+"</div>]]></content:encoded>"
+" <wfw:commentRss>http://mihaibalan.wordpress.com/2007/08/16/tuig-pa"
+"tiently-waiting/feed/</wfw:commentRss>"
+" </item>";
/**
* String containing the body of a new RSS feed.
*/
private static String rssBodyNew = " <item>"
+" <title>I see trees of green and skies of blue</title>"
+" <link>http://mihaibalan.wordpress.com/2007/08/21/i-see-trees-of-gr"
+"een-and-skies-of-blue/</link>"
+" <comments>http://mihaibalan.wordpress.com/2007/08/21/i-see-trees-of"
+"-green-and-skies-of-blue/#comments</comments>"
+" <pubDate>Mon, 20 Aug 2007 22:20:57 +0000</pubDate>"
+" <dc:creator>mich0u</dc:creator>"
+" <category><![CDATA[tree]]></category>"
+" <category><![CDATA[bucharest]]></category>"
+" <category><![CDATA[architecture]]></category>"
+" <guid isPermaLink=\"false\">http://mihaibalan.wordpress.com/2007"
+"/08/21/i-see-trees-of-green-and-skies-of-blue/</guid>"
+" <description><![CDATA["
+"]]></description>"
+" <content:encoded><![CDATA[<div class='snap_preview'><p align=\"cent"
+"er\"><a href=\"http://www.zooomr.com/photos/michou/2997760/\" title=\"Ph"
+"oto Sharing\"><img src=\"http://static.zooomr.com/images/2997760_f5a39d2a"
+"db.jpg\" alt=\"I see trees of green, and skies of blue\" style=\"border:"
+"medium none;\" height=\"340\" width=\"500\" /></a></p>"
+"</div>]]></content:encoded>"
+" <wfw:commentRss>http://mihaibalan.wordpress.com/2007/08/21/i-see"
+"-trees-of-green-and-skies-of-blue/feed/</wfw:commentRss>"
+" </item>"
+" <item>"
+" <title>Tuig - If I could turn back time</title>"
+" <link>http://mihaibalan.wordpress.com/2007/08/20/tuig-if-i-could-"
+"turn-back-time/</link>"
+" <comments>http://mihaibalan.wordpress.com/2007/08/20/tuig-if-i-"
+"could-turn-back-time/#comments</comments>"
+" <pubDate>Sun, 19 Aug 2007 22:05:53 +0000</pubDate>"
+" <dc:creator>mich0u</dc:creator>"
+" <category><![CDATA[light]]></category>"
+" <category><![CDATA[long exposure]]></category>"
+" <category><![CDATA[dark]]></category>"
+" <guid isPermaLink=\"false\">http://mihaibalan.wordpress.com/2007/"
+"08/20/tuig-if-i-could-turn-back-time/</guid>"
+" <description><![CDATA["
+"]]></description>"
+" <content:encoded><![CDATA[<div class='snap_preview'><p align=\"cent"
+"er\"><a href=\"http://www.flickr.com/photos/mi-chou/1029399905/\" title="
+"\"Photo Sharing\"><img src=\"http://farm2.static.flickr.com/1191/10293999"
+"05_08e5d41b89.jpg\" alt=\"Tuig - If I could roll back time\" style=\""
+"border:medium none;\" height=\"383\" width=\"500\" /></a></p>"
+"<p> <a href=\"http://mihaibalan.wordpress.com/2007/08/20/tuig-if-i-could-"
+"turn-back-time/#more-122\" class=\"more-link\">(more&#8230;)</a></p>"
+"</div>]]></content:encoded>"
+" <wfw:commentRss>http://mihaibalan.wordpress.com/2007/08/20/tuig-if"
+"-i-could-turn-back-time/feed/</wfw:commentRss>"
+" </item>";
/**
* String containing some invalid mark-up in the RSS feed.
*/
private static String rssBodyInvalid =
"<some-invalid-tag attr='value1'>Lorem ipsum</some-invalid-tg>";
/**
* String containing the footer of a RSS feed.
*/
private static String rssFooter = "</channel></rss>";
/**
* String containing the header of a ATOM feed.
*/
private static String atomHeader =
"<?xml version='1.0' encoding='UTF-8'?>"
+"<?xml-stylesheet href=\"http://www.blogger.com/styles/atom.css\" type=\""
+"text/css\"?>"
+"<feed xmlns='http://www.w3.org/2005/Atom' xmlns:openSearch='http://a9.co"
+"m/-/spec/opensearchrss/1.0/'>"
+" <id>tag:blogger.com,1999:blog-3490925879145756058</id><updated>2007-"
+"08-08T10:24:42.424-07:00</updated><title type='text'>miChou's Summer of "
+"Code blog</title><link rel='alternate' type='text/html' href='http://ete"
+"-de-code-a-la-chou.blogspot.com/'/>"
+" <link rel='http://schemas.google.com/g/2005#feed' type='application/"
+"atom+xml' href='http://ete-de-code-a-la-chou.blogspot.com/feeds/posts/de"
+"fault'/>"
+" <link rel='self' type='application/atom+xml' href='http://ete-de-cod"
+"e-a-la-chou.blogspot.com/feeds/posts/default'/>"
+" <author>"
+" <name>Mihai Balan</name>"
+" </author>"
+" <generator version='7.00' uri='http://www.blogger.com'>Blogger</gene"
+"rator><openSearch:totalResults>6</openSearch:totalResults><openSearch:st"
+"artIndex>1</openSearch:startIndex><openSearch:itemsPerPage>25</openSearc"
+"h:itemsPerPage>";
/**
* String containing the body of an ATOM feed.
*/
private static String atomBody =
"<entry><id>tag:blogger.com,1999:blog-3490925879145756058.post-445569517"
+"5541848605</id><published>2007-06-05T02:15:00.000-07:00</published><upda"
+"ted>2007-06-05T03:34:35.892-07:00</updated><category scheme='http://www."
+"blogger.com/atom/ns#' term='soc'/>"
+" <category scheme='http://www.blogger.com/atom/ns#' term='todo'/>"
+""
+" <title type='text'>Happy hacking!</title><content type='html'>Fi"
+"nally the second semester is over, and the summer exams sessions is abou"
+"t to begin (that means I have the first exam tomorrow - Digital Computer"
+"s 2).And in between all this, I should also get my exams going :)</conte"
+"nt><link rel='alternate' type='text/html' href='http://ete-de-code-a-la-"
+"chou.blogspot.com/2007/06/happy-hacking.html' title='Happy hacking!'/>"
+" <link rel='replies' type='text/html' href='http://www.blogger.co"
+"m/comment.g?blogID=3490925879145756058&amp;postID=4455695175541848605' t"
+"itle='0 Comments'/>"
+" <link rel='replies' type='application/atom+xml' href='http://ete"
+"-de-code-a-la-chou.blogspot.com/feeds/4455695175541848605/comments/defau"
+"lt' title='Post Comments'/>"
+" <link rel='self' type='application/atom+xml' href='http://ete-de"
+"-code-a-la-chou.blogspot.com/feeds/posts/default/4455695175541848605'/>"
+" <link rel='edit' type='application/atom+xml' href='http://www.bl"
+"ogger.com/feeds/3490925879145756058/posts/default/4455695175541848605'/>"
+""
+" <author>"
+" <name>Mihai Balan</name>"
+" </author>"
+" </entry>"
+" <entry>"
+" <id>tag:blogger.com,1999:blog-3490925879145756058.post-160551373"
+"861169805</id><published>2007-05-31T13:34:00.000-07:00</published><updat"
+"ed>2007-06-01T04:21:00.167-07:00</updated><category scheme='http://www.b"
+"logger.com/atom/ns#' term='soc'/>"
+" <category scheme='http://www.blogger.com/atom/ns#' term='francai"
+"s'/>"
+" <category scheme='http://www.blogger.com/atom/ns#' term='bla-bla"
+"'/>"
+" <title type='text'>Un debut attarde</title><content type='html'>"
+"&lt;span style=\"font-style: italic;font-size:100%;\" &gt;&lt;span style="
+"\"font-family:georgia;\"&gt;Bien qu'on m'ait dit que toute communication "
+"regardant SIP se fera en anglais je prends le risque d'ecrire ce premier "
+"post en francais.</content><link rel='alternate' type='text/html' href='h"
+"ttp://ete-de-code-a-la-chou.blogspot.com/2007/05/un-debut-attarde.html' "
+"title='Un debut attarde'/>"
+" <link rel='replies' type='text/html' href='http://www.blogger.co"
+"m/comment.g?blogID=3490925879145756058&amp;postID=160551373861169805' ti"
+"tle='0 Comments'/>"
+" <link rel='replies' type='application/atom+xml' href='http://ete"
+"-de-code-a-la-chou.blogspot.com/feeds/160551373861169805/comments/defaul"
+"t' title='Post Comments'/>"
+" <link rel='self' type='application/atom+xml' href='http://ete-de"
+"-code-a-la-chou.blogspot.com/feeds/posts/default/160551373861169805'/>"
+" <link rel='edit' type='application/atom+xml' href='http://www.bl"
+"ogger.com/feeds/3490925879145756058/posts/default/160551373861169805'/>"
+" <author>"
+" <name>Mihai Balan</name>"
+" </author>"
+" </entry>";
/**
* String containing the updates to the ATOM feed.
*/
private static String atomBodyUpdate =
"<entry><id>tag:blogger.com,1999:blog-3490925879145756058.post-722978588"
+"3825532193</id><published>2007-06-25T14:29:00.000-07:00</published><upda"
+"ted>2007-06-26T06:12:44.479-07:00</updated><category scheme='http://www."
+"blogger.com/atom/ns#' term='bugzilla'/>"
+" <category scheme='http://www.blogger.com/atom/ns#' term='todo'/>"
+""
+" <category scheme='http://www.blogger.com/atom/ns#' term='google'"
+"/>"
+" <category scheme='http://www.blogger.com/atom/ns#' term='rss'/>"
+" <title type='text'>Google politics</title><content type='html'>O"
+"ne of the problems well known in the current implementation of the RSS s"
+"upport in SIP Communicator was the inability to retrieve feeds from news"
+".google.com (and you must admit, news.google.com is quite a source of ne"
+"ws ;) ).&lt;br /&gt;&lt;br /&gt; A brief look at the exception returned"
+" by the plugin points out the problem. The server is sending a HTTP/403 "
+"(Forbidden) response code instead of the HTTP/200 (OK) response code.</c"
+"ontent><link rel='alternate' type='text/html' href='http://ete-de-code-a"
+"-la-chou.blogspot.com/2007/06/google-politics.html' title='Google politi"
+"cs'/>"
+" <link rel='replies' type='text/html' href='http://www.blogger.co"
+"m/comment.g?blogID=3490925879145756058&amp;postID=7229785883825532193' t"
+"itle='0 Comments'/>"
+" <link rel='replies' type='application/atom+xml' href='http://ete"
+"-de-code-a-la-chou.blogspot.com/feeds/7229785883825532193/comments/defau"
+"lt' title='Post Comments'/>"
+" <link rel='self' type='application/atom+xml' href='http://ete-de"
+"-code-a-la-chou.blogspot.com/feeds/posts/default/7229785883825532193'/>"
+" <link rel='edit' type='application/atom+xml' href='http://www.bl"
+"ogger.com/feeds/3490925879145756058/posts/default/7229785883825532193'/>"
+""
+" <author>"
+" <name>Mihai Balan</name>"
+" </author>"
+" </entry>";
/**
* String containing a new ATOM feed.
*/
private static String atomBodyNew =
"<entry><id>tag:blogger.com,1999:blog-3490925879145756058.post-325829288"
+"5225110686</id><published>2007-08-08T09:59:00.000-07:00</published><upda"
+"ted>2007-08-08T10:24:42.470-07:00</updated><category scheme='http://www."
+"blogger.com/atom/ns#' term='todo'/>"
+" <category scheme='http://www.blogger.com/atom/ns#' term='new fea"
+"ture'/>"
+" <category scheme='http://www.blogger.com/atom/ns#' term='emil'/>"
+""
+" <category scheme='http://www.blogger.com/atom/ns#' term='rss'/>"
+" <title type='text'>check out. again...</title><content type='htm"
+"l'>&lt;div style=\"text-align: justify;\"&gt;It seems I do have a strange"
+" problem when it comes to using CVS. It's not version control systems in "
+"general, but CVS. Or at least, the CVS I'm using here, on Sip Communicat"
+"or. Somehow, I never get it right.</content><link rel='alternate' type='"
+"text/html' href='http://ete-de-code-a-la-chou.blogspot.com/2007/08/check"
+"-out-again.html' title='check out. again...'/>"
+" <link rel='replies' type='text/html' href='http://www.blogger.co"
+"m/comment.g?blogID=3490925879145756058&amp;postID=3258292885225110686' t"
+"itle='0 Comments'/>"
+" <link rel='replies' type='application/atom+xml' href='http://ete"
+"-de-code-a-la-chou.blogspot.com/feeds/3258292885225110686/comments/defau"
+"lt' title='Post Comments'/>"
+" <link rel='self' type='application/atom+xml' href='http://ete-de"
+"-code-a-la-chou.blogspot.com/feeds/posts/default/3258292885225110686'/>"
+" <link rel='edit' type='application/atom+xml' href='http://www.bl"
+"ogger.com/feeds/3490925879145756058/posts/default/3258292885225110686'/>"
+""
+" <author>"
+" <name>Mihai Balan</name>"
+" </author>"
+" </entry>"
+" <entry>"
+" <id>tag:blogger.com,1999:blog-3490925879145756058.post-186104691"
+"5714479007</id><published>2007-07-06T13:23:00.000-07:00</published><upda"
+"ted>2007-07-06T13:54:46.478-07:00</updated><category scheme='http://www."
+"blogger.com/atom/ns#' term='new feature'/>"
+" <category scheme='http://www.blogger.com/atom/ns#' term='questio"
+"n'/>"
+" <category scheme='http://www.blogger.com/atom/ns#' term='rss'/>"
+" <title type='text'>Favicon - check!</title><content type='html'>"
+"&lt;div style=\"text-align: justify;\"&gt;Finally, favicon retrieval supp"
+"ort is here. What is this all about? Almost all IM protocols out there al"
+"low you to specify and associate an image to your account (a so called a"
+"vatar), either natively (e.g. Y!M), either through extensions (e.g. XMPP"
+"/Jabber).</content><link rel='alternate' type='text/html' href='http://e"
+"te-de-code-a-la-chou.blogspot.com/2007/07/favicon-check.html' title='Fav"
+"icon - check!'/>"
+" <link rel='replies' type='text/html' href='http://www.blogger.co"
+"m/comment.g?blogID=3490925879145756058&amp;postID=1861046915714479007' t"
+"itle='0 Comments'/>"
+" <link rel='replies' type='application/atom+xml' href='http://ete"
+"-de-code-a-la-chou.blogspot.com/feeds/1861046915714479007/comments/defau"
+"lt' title='Post Comments'/>"
+" <link rel='self' type='application/atom+xml' href='http://ete-de"
+"-code-a-la-chou.blogspot.com/feeds/posts/default/1861046915714479007'/>"
+" <link rel='edit' type='application/atom+xml' href='http://www.bl"
+"ogger.com/feeds/3490925879145756058/posts/default/1861046915714479007'/>"
+""
+" <author>"
+" <name>Mihai Balan</name>"
+" </author>"
+" </entry>"
+" <entry>"
+" <id>tag:blogger.com,1999:blog-3490925879145756058.post-717349866"
+"079669848</id><published>2007-06-29T12:35:00.000-07:00</published><updat"
+"ed>2007-06-29T12:39:34.816-07:00</updated><category scheme='http://www.b"
+"logger.com/atom/ns#' term='bugzilla'/>"
+" <category scheme='http://www.blogger.com/atom/ns#' term='todo'/>"
+""
+" <title type='text'>Interim objectives</title><content type='html"
+"'>I know I've been a little late setting these, but now it's kinda' sett"
+"led.</content><link rel='alternate' type='text/html' href='http://ete-de"
+"-code-a-la-chou.blogspot.com/2007/06/interim-objectives.html' title='Int"
+"erim objectives'/>"
+" <link rel='replies' type='text/html' href='http://www.blogger.co"
+"m/comment.g?blogID=3490925879145756058&amp;postID=717349866079669848' ti"
+"tle='0 Comments'/>"
+" <link rel='replies' type='application/atom+xml' href='http://ete"
+"-de-code-a-la-chou.blogspot.com/feeds/717349866079669848/comments/defaul"
+"t' title='Post Comments'/>"
+" <link rel='self' type='application/atom+xml' href='http://ete-de"
+"-code-a-la-chou.blogspot.com/feeds/posts/default/717349866079669848'/>"
+" <link rel='edit' type='application/atom+xml' href='http://www.bl"
+"ogger.com/feeds/3490925879145756058/posts/default/717349866079669848'/>"
+" <author>"
+" <name>Mihai Balan</name>"
+" </author>"
+" </entry>";
/**
* String containing some invalid markup in the ATOM feed.
*/
private static String atomBodyInvalid =
"<some-invalid-tag attr='value1'>Lorem ipsum</some-invalid-tg>";
/**
* String containing the footer of the ATOM feed.
*/
private static String atomFooter = "</feed>";
/**
* Returns a <code>String</code> representing an RSS feed.
* @return textual representation of the RSS feed.
*/
public static String getRss()
{
return rssHeader + rssBody + rssFooter;
}
/**
* Returns a <code>String</code> representing the updated RSS feed.
* @return textual representation of the RSS feed.
*/
public static String getRssUpdated()
{
return rssHeader + rssBodyUpdate + rssBody + rssFooter;
}
/**
* Returns a <code>String</code> representing a new version of the RSS feed.
* @return textual representation of the RSS feed.
*/
public static String getRssNew()
{
return rssHeader + rssBodyNew + rssFooter;
}
/**
* Returns a <code>String</code> representing an invalid RSS feed.
* @return textual representation of the RSS feed.
*/
public static String getRssInvalid()
{
return rssHeader + rssBodyInvalid + rssFooter;
}
/**
* Returns a <code>String</code> representing an ATOM feed.
* @return textual representation of the RSS feed.
*/
public static String getAtom()
{
return atomHeader + atomBody + atomFooter;
}
/**
* Returns a <code>String</code> representing the updated ATOM feed.
* @return textual representation of the RSS feed.
*/
public static String getAtomUpdated()
{
return atomHeader + atomBodyUpdate + atomBody + atomFooter;
}
/**
* Returns a <code>String</code> representing a new version of the ATOM
* feed.
* @return textual representation of the RSS feed.
*/
public static String getAtomNew()
{
return atomHeader + atomBodyNew + atomFooter;
}
/**
* Returns a <code>String</code> representing an invalid ATOM feed.
* @return textual representation of the RSS feed.
*/
public static String getAtomInvalid()
{
return atomHeader + atomBodyInvalid + atomFooter;
}
}

@ -0,0 +1,67 @@
/*
* SIP Communicator, the OpenSource Java VoIP and Instant Messaging client.
*
* Distributable under LGPL license.
* See terms of license at gnu.org.
*/
package net.java.sip.communicator.slick.protocol.rss;
import java.util.*;
import junit.framework.*;
import net.java.sip.communicator.util.*;
import org.osgi.framework.*;
/**
* RSS specific testing for an RSS Protocol provider Service implementation.
* [...]
* @author Mihai Balan
*/
public class RssProtocolProviderServiceLick
extends TestSuite
implements BundleActivator
{
/**
* Initializes and registers all tests that we'll run as a part of this
* SLICK.
*
* @param bundleContext a currently valid bundle context.
*/
public void start(BundleContext bundleContext)
{
Logger logger =
Logger.getLogger(RssProtocolProviderServiceLick.class);
logger.setLevelAll();
logger.debug("***Start() called on RSS slick***");
setName("RssProtocolProviderServiceLick");
Hashtable properties = new Hashtable();
properties.put("service.pid", getName());
RssSlickFixture.bc = bundleContext;
//test account installation
addTestSuite(TestAccountInstallation.class);
//test Protocol Provider Service implementation
addTestSuite(TestProtocolProviderServiceRssImpl.class);
//test account uninstallation
addTest(TestAccountUninstallation.suite());
addTestSuite(TestAccountUninstallationPersistence.class);
bundleContext.registerService(getClass().getName(), this, properties);
}
/**
* Prepares the slick for shutdown.
*
* @param context a currently valid bundle context.
*/
public void stop(BundleContext context)
{
}
}

@ -0,0 +1,155 @@
/*
* SIP Communicator, the OpenSource Java VoIP and Instant Messaging client.
*
* Distributable under LGPL license.
* See terms of license at gnu.org.
*/
package net.java.sip.communicator.slick.protocol.rss;
import java.util.*;
import junit.framework.*;
import org.osgi.framework.*;
import net.java.sip.communicator.service.protocol.*;
/**
* Contains constants and methods used by almost all of our tests.
*
* @author Mihai Balan
*/
public class RssSlickFixture
extends TestCase
{
/**
* To be set by the slick itself upon activation.
*/
public static BundleContext bc = null;
/**
* And OSGi service reference for the protocol provider corresponding to our
* testing account.
*/
public ServiceReference providerServiceReference = null;
/**
* Protocol provider corresponding to the testing account.
*/
public ProtocolProviderService provider = null;
/**
* The user ID associated with the testing account.
*/
//public String userId = null;
public ProtocolProviderFactory providerFactory = null;
/**
* A reference to the bundle containing the tested ProtocolProvider
* implementation. This reference is set during the account installation
* testing and used during the account installation persistence testing.
*/
public static Bundle providerBundle = null;
/**
* A <code>HashTable</code> containing group names mapped against array
* lists of buddy screen names.
*/
public static Hashtable preInstalledBuddyList = null;
//XXX: Do I really need that? :-\
/**
* Initializes protocol provider references and whatever else there is to
* initialize.
*
* @throws java.lang.Exception in case we meet problems while retriving
* protocol providers through OSGI
*/
public void setUp()
throws Exception
{
//get a reference to the provider factory
ServiceReference[] serRefs = null;
String osgiFilter = "(" + ProtocolProviderFactory.PROTOCOL
+ "=" + ProtocolNames.RSS + ")";
try {
serRefs = bc.getServiceReferences(
ProtocolProviderFactory.class.getName(), osgiFilter);
} catch (InvalidSyntaxException ise)
{
//shouldn't happen as the filter is static (typos maybe? :D)
fail(osgiFilter + "is not a valid OSGi filter");
}
assertTrue("Failed to find a provider factory service for protocol RSS",
serRefs != null && serRefs.length > 0);
providerFactory = (ProtocolProviderFactory)bc.getService(serRefs[0]);
//find the protocol providers exported for the two accounts
ServiceReference[] rssProviderRefs = bc.getServiceReferences(
ProtocolProviderService.class.getName(),
"(&("+ProtocolProviderFactory.PROTOCOL+"="+ProtocolNames.RSS+"))");
//make sure we found a service
assertNotNull("No protocol provider was found for RSS account ",
rssProviderRefs);
assertTrue("No protocol provider was found for RSS account",
rssProviderRefs.length > 0);
//save the service for other tests to use.
providerServiceReference = rssProviderRefs[0];
provider = (ProtocolProviderService)bc.getService(
providerServiceReference);
}
/**
* Un get service references used in here.
*/
public void tearDown()
{
bc.ungetService(providerServiceReference);
}
/**
* Returns the bundle that has registered the protocol provider service
* implementation that we're currently testing. The method would go through
* all bundles currently installed in the framework and return the first
* one that exports the same protocol provider instance as the one we test
* in this slick.
*
* @param provider the provider whose bundle we're looking for.
* @return the Bundle that has registered the protocol provider service
* we're testing in the slick.
*/
public static Bundle findProtocolProviderBundle(
ProtocolProviderService provider)
{
Bundle[] bundles = bc.getBundles();
for (int i = 0; i < bundles.length; i++)
{
ServiceReference[] registeredServices
= bundles[i].getRegisteredServices();
if (registeredServices == null)
continue;
for (int j = 0; j < registeredServices.length; j++)
{
Object service
= bc.getService(registeredServices[j]);
if (service == provider)
return bundles[i];
}
}
return null;
}
public void clearProvidersList()
throws Exception
{
//XXX: FTM, do_nothing()
}
}

@ -0,0 +1,133 @@
/*
* SIP Communicator, the OpenSource Java VoIP and Instant Messaging client.
*
* Distributable under LGPL license.
* See terms of license at gnu.org.
*/
package net.java.sip.communicator.slick.protocol.rss;
import org.osgi.framework.*;
import net.java.sip.communicator.service.protocol.*;
import net.java.sip.communicator.util.*;
import junit.framework.*;
import java.util.*;
/**
* Installs a test account and verifies it is available after installation.
*
* @author Mihai Balan
*/
public class TestAccountInstallation
extends TestCase
{
private static final Logger logger =
Logger.getLogger(TestAccountInstallation.class);
/**
* Creates a test with the specified method name.
* @param name the name of the method tu execute.
*/
public TestAccountInstallation(String name)
{
super(name);
}
/**
* JUnit setup method.
*/
protected void setUp() throws Exception
{
super.setUp();
}
/**
* JUnit cleanup method.
*/
protected void tearDown() throws Exception
{
super.tearDown();
}
/**
* Installs and account and verifies whether the installation succedded.
*/
public void testInstallAccount()
{
Hashtable accountProperties = new Hashtable();
ServiceReference[] serRefs = null;
String osgiFilter = "(" + ProtocolProviderFactory.PROTOCOL + "="
+ ProtocolNames.RSS + ")";
accountProperties.put(ProtocolProviderFactory.USER_ID, "RSS");
try {
serRefs = RssSlickFixture.bc.getServiceReferences(
ProtocolProviderFactory.class.getName(), osgiFilter);
} catch (InvalidSyntaxException ise)
{
//shouldn't happen as the filter is static
fail(osgiFilter + "is not a valid filter");
}
//couldn't find a provider factory service.
assertTrue("Failed to find a provider factory service or protocol RSS",
serRefs != null && serRefs.length > 0);
ProtocolProviderFactory rssProviderFactory = (ProtocolProviderFactory)
RssSlickFixture.bc.getService(serRefs[0]);
//there shouldn't be any account installed
assertTrue("There was an account already registered with the account "
+ "manager",
rssProviderFactory.getRegisteredAccounts().size() == 0);
try {
rssProviderFactory.installAccount(null, accountProperties);
fail("Installing an account with a null account id must result in a"
+ " NullPointerException!");
} catch(NullPointerException npe)
{
//that's ought to happen
}
rssProviderFactory.installAccount("RSS", accountProperties);
//try to install the same account twice and check for exceptions
try {
rssProviderFactory.installAccount("RSS", accountProperties);
fail("An IllegalStateException must be thrown when trying to "
+ "install a duplicate account.");
} catch(IllegalStateException ise)
{
//that's ought to happen
}
assertTrue("Newly installed account is not in the account manager's "
+ "registered accounts!",
rssProviderFactory.getRegisteredAccounts().size() == 1);
osgiFilter = "(&(" + ProtocolProviderFactory.PROTOCOL + "="
+ ProtocolNames.RSS + ")"
+ "(" + ProtocolProviderFactory.USER_ID + "=RSS))";
try {
serRefs = RssSlickFixture.bc.getServiceReferences(
ProtocolProviderService.class.getName(), osgiFilter);
} catch(InvalidSyntaxException ise)
{
fail(osgiFilter + " is not a valid filter");
}
assertTrue("A protocol provider was apparently not installed as"
+ " requested",
serRefs != null && serRefs.length > 0);
Object rssProtocolProvider =
RssSlickFixture.bc.getService(serRefs[0]);
assertTrue("The installed protocol provider does not implement the"
+ "protocol provider service.",
rssProtocolProvider instanceof ProtocolProviderService);
}
}

@ -0,0 +1,211 @@
/*
* SIP Communicator, the OpenSource Java VoIP and Instant Messaging client.
*
* Distributable under LGPL license.
* See terms of license at gnu.org.
*/
package net.java.sip.communicator.slick.protocol.rss;
import junit.framework.*;
import org.osgi.framework.*;
import net.java.sip.communicator.util.*;
import net.java.sip.communicator.service.protocol.*;
/**
* Tests whether accounts are uninstalled properly. It is important that
* tests from this class be called last since they will install the accounts
* that have been used to test the implementations. Apart from uninstallation
* tests the class also contains tests that remove and reinstall the protocol
* provider bundle in order to verify that accounts are persistent.
*
* @author Mihai Balan
*/
public class TestAccountUninstallation
extends TestCase
{
private Logger logger = Logger.getLogger(TestAccountUninstallation.class);
private RssSlickFixture fixture = new RssSlickFixture();
/**
* Constructs a test instance
* @param name The name of the test.
*/
public TestAccountUninstallation(String name)
{
super(name);
}
/**
* JUnit setup method.
* @throws Exception in case anything goes wrong.
*/
public void setUp() throws Exception
{
super.setUp();
fixture.setUp();
}
/**
* JUnit teardown method.
* @throws Exception in case anything goes wrong.
*/
public void tearDown() throws Exception
{
fixture.tearDown();
super.tearDown();
}
/**
* Returns a suite containing tests in this class in the order that we'd
* like them executed.
* @return a Test suite containing tests in this class in the order that
* we'd like them executed.
*/
public static Test suite()
{
TestSuite suite = new TestSuite();
suite.addTest(
new TestAccountUninstallation("testInstallationPersistence"));
suite.addTest(
new TestAccountUninstallation("testUninstallAccount"));
return suite;
}
/**
* Stops and removes the tested bundle, verifies that it has unregistered
* its provider, then reloads and restarts the bundle and verifies that
* the protocol provider is reRegistered in the bundle context.
*
* @throws java.lang.Exception if an exception occurs during testing.
*/
public void testInstallationPersistence() throws Exception
{
Bundle providerBundle =
fixture.findProtocolProviderBundle(fixture.provider);
//set the global providerBundle reference that we will be using
//in the last series of tests (Account uninstallation persistency)
RssSlickFixture.providerBundle = providerBundle;
assertNotNull("Couldn't find a bundle for the protocol provider",
providerBundle);
providerBundle.stop();
assertTrue("Couldn't stop protocol provider bundle. State was "
+ providerBundle.getSymbolicName(),
providerBundle.getState() != Bundle.ACTIVE
&& providerBundle.getState() != Bundle.STOPPING);
providerBundle.uninstall();
assertEquals("Couldn't uninstall protocol provider bundle.",
providerBundle.getState(), Bundle.UNINSTALLED);
//verify that the provider is no longer available
ServiceReference providerRefs[] = null;
try {
providerRefs = fixture.bc.getServiceReferences(
ProtocolProviderService.class.getName(),
"(&(" + ProtocolProviderFactory.PROTOCOL + "="
+ ProtocolNames.RSS + "))");
} catch (InvalidSyntaxException ise)
{
fail("Invalid OSGi filter. Exception was" + ise.getMessage());
}
//verify the provider really uninstalled
assertTrue("Protocol provider still present after being explicitly" +
" uninstalled",
providerRefs == null || providerRefs.length == 0);
assertTrue("The RSS protocol provider factory didn't completely "
+ "uninstalled the provider service",
fixture.providerFactory.getRegisteredAccounts().size() == 0 &&
fixture.providerFactory.getProviderForAccount(
fixture.provider.getAccountID()) == null);
//reinstall provider
providerBundle = fixture.bc.installBundle(providerBundle.getLocation());
RssSlickFixture.providerBundle = providerBundle;
assertTrue("Couldn't reinstall provider bundle",
providerBundle.getState() == Bundle.INSTALLED);
providerBundle.start();
assertTrue("Couldn't start provider",
providerBundle.getState() == Bundle.ACTIVE);
providerRefs = null;
try {
providerRefs = fixture.bc.getServiceReferences(
ProtocolProviderService.class.getName(),
"(&(" + ProtocolProviderFactory.PROTOCOL + "="
+ ProtocolNames.RSS + "))");
} catch (InvalidSyntaxException ise)
{
fail("Invalid OSGi filter. Exception was" + ise.getMessage());
}
assertTrue("The protocol provider hasn't been restored after being "
+ "reinstalled",
providerRefs != null && providerRefs.length > 0);
ServiceReference factoryRefs[] = null;
try {
factoryRefs = fixture.bc.getServiceReferences(
ProtocolProviderFactory.class.getName(),
"(" + ProtocolProviderFactory.PROTOCOL + "=RSS)");
} catch (InvalidSyntaxException ise)
{
fail("Invalid OSGi filter. Exception was " + ise.getMessage());
}
fixture.providerFactory =
(ProtocolProviderFactory) fixture.bc.getService(factoryRefs[0]);
fixture.provider =
(ProtocolProviderService) fixture.bc.getService(providerRefs[0]);
assertFalse("RSS provider did not restore its own reference to the"
+ " provider that we just reinstalled.",
fixture.providerFactory.getRegisteredAccounts().isEmpty()
&& fixture.providerFactory.getProviderForAccount(
fixture.provider.getAccountID()) == null);
}
/**
* Unistalls our test account and makes sure it really has been removed.
*/
public void testUninstallAccount() throws Exception
{
assertTrue("No accounts found.",
! fixture.providerFactory.getRegisteredAccounts().isEmpty());
assertNotNull("Found no provider corresponding to RSS",
fixture.providerFactory.getProviderForAccount(
fixture.provider.getAccountID()));
assertTrue("Failed to remove provider",
fixture.providerFactory.uninstallAccount(
fixture.provider.getAccountID()));
ServiceReference[] providerRefs = null;
try {
providerRefs = fixture.bc.getServiceReferences(
ProtocolProviderService.class.getName(),
"(" + ProtocolProviderFactory.PROTOCOL + "=" + ProtocolNames.RSS
+ ")");
} catch (InvalidSyntaxException ise)
{
fail("Invalid OSGi filter.Exception was: " + ise.getMessage());
}
assertTrue("Protocol provider service still registered as OSGi service",
providerRefs == null || providerRefs.length == 0);
assertTrue("Provider factory didn't properly uninstalled the provider"
+ "service we just uninstalled",
fixture.providerFactory.getRegisteredAccounts().isEmpty()
&& fixture.providerFactory.getProviderForAccount(
fixture.provider.getAccountID()) == null);
}
}

@ -0,0 +1,92 @@
/*
* SIP Communicator, the OpenSource Java VoIP and Instant Messaging client.
*
* Distributable under LGPL license.
* See terms of license at gnu.org.
*/
package net.java.sip.communicator.slick.protocol.rss;
import junit.framework.*;
import org.osgi.framework.*;
import net.java.sip.communicator.service.configuration.*;
import net.java.sip.communicator.service.protocol.*;
/**
* Contains tests verifying persistence of account uninstallation. In other
* words we try to make sure that once uninstalled an account remains
* uninstalled.
*
* @author Mihai Balan
*/
public class TestAccountUninstallationPersistence
extends TestCase
{
/**
* Creates a new test instance wrapper around the test with the specified
* name.
*
* @param testName the name of the test that we will be executing.
*/
public TestAccountUninstallationPersistence(String testName)
{
super(testName);
}
/**
* Retrieves a reference to the RSS bundle, stops and uninstalls it and then
* reinstalls it in order to make sure that accounts are not reloaded once
* removed.
*
* @throws Exception if anything goes wrong while manipulating the bundles.
*/
public void testAccountUninstallationPersistence()
throws Exception
{
Bundle providerBundle = RssSlickFixture.providerBundle;
providerBundle.stop();
assertTrue("Couldn't stop the protocol provider bundle. State was"
+ providerBundle.getState(),
providerBundle.getState() != Bundle.ACTIVE
&& providerBundle.getState() != Bundle.STOPPING);
providerBundle.uninstall();
assertEquals("Couldn't stop the protocol provider bundle.",
providerBundle.getState(), Bundle.UNINSTALLED);
//now reinstall the bundle and restart the provider
providerBundle = RssSlickFixture.bc.installBundle(
providerBundle.getLocation());
assertEquals("Couldn't reinstall protocol provider bundle.",
providerBundle.getState(), Bundle.INSTALLED);
providerBundle.start();
assertEquals("Couldn't restart protocol provider bundle.",
providerBundle.getState(), Bundle.ACTIVE);
//verify the provider is not reinstalled
ServiceReference[] providerRefs = null;
try {
providerRefs = RssSlickFixture.bc.getServiceReferences(
ProtocolProviderService.class.getName(),
"(" + ProtocolProviderFactory.PROTOCOL + "=" + ProtocolNames.RSS
+ ")");
} catch (InvalidSyntaxException ise)
{
fail("OSGi filter is wrong. Error was: " + ise.getMessage());
}
//make sure we didn't retrieve a service
assertTrue("An RSS protocol provider service was still registered as an"
+ " OSGi service even after being explicitly uninstalled",
providerRefs == null || providerRefs.length == 0);
//now delete configuration file for a fresh start for the next test
ServiceReference confRef = RssSlickFixture.bc.getServiceReference(
ConfigurationService.class.getName());
ConfigurationService confServ =
(ConfigurationService) RssSlickFixture.bc.getService(confRef);
confServ.purgeStoredConfiguration();
}
}

@ -0,0 +1,235 @@
/*
* SIP Communicator, the OpenSource Java VoIP and Instant Messaging client.
*
* Distributable under LGPL license.
* See terms of license at gnu.org.
*/
package net.java.sip.communicator.slick.protocol.rss;
import junit.framework.*;
import net.java.sip.communicator.service.protocol.*;
import net.java.sip.communicator.service.protocol.event.*;
import net.java.sip.communicator.util.*;
import java.util.*;
/**
* This class performs testing on protocol provider methods. It verifies that
* the protocol provider service implements the declared operation sets and also
* tests the process of registering an account.
*
* @author Mihai Balan
*/
public class TestProtocolProviderServiceRssImpl
extends TestCase
{
/**
* Time in miliseconds to wait for registration to complete. Is subject to
* further fine-tuning.
*/
public static final int WAIT_DELAY = 10000;
public static final Logger logger =
Logger.getLogger(TestProtocolProviderServiceRssImpl.class);
/**
* Test's fixture.
*/
private RssSlickFixture fixture = new RssSlickFixture();
public RegistrationEventCollector eventCollector =
new RegistrationEventCollector();
/**
* Creates a test case that runs the specified test.
*
* @param testName the name of the method the test should run.
*/
public TestProtocolProviderServiceRssImpl(String testName)
{
super(testName);
}
/**
* Initializes the fixture.
*
* @throws Exception if <code>super.setUp()</code> throws one.
*/
public void setUp() throws Exception
{
super.setUp();
fixture.setUp();
}
/**
* Cleans up after the test.
*
* @throws Exception if <code>fixture.tearDown()</code> fails.
*/
public void tearDown() throws Exception
{
fixture.tearDown();
super.tearDown();
}
/**
* This methods makes sure that the instance of the RSS protocol provider
* that we are going to use is properly initialized and registered. It also
* verifies that a registration event is fired upon successful registration
* and collected by our event collector.
*
* @throws OperationFailedException if <code>provider.register()</code>
* fails.
*/
public void testRegister() throws OperationFailedException
{
//registering as a listener & starting registration with a
//null SecurityAuthority
fixture.provider.addRegistrationStateChangeListener(
this.eventCollector);
fixture.provider.register(new NullSecurityAuthority());
//give it a little time to do his magic ;)
logger.debug("Waiting for registration to complete...");
eventCollector.waitForEvent(WAIT_DELAY);
//make sure we received events...
assertTrue("No events were dispatched during the registration process.",
eventCollector.collectedStates.size() > 0);
//...and they were the right ones
assertTrue("No registration event notifying of registration was"
+ " dispatched."
+ " All events were:" + eventCollector.collectedStates,
eventCollector.collectedStates.contains(
RegistrationState.REGISTERED));
//if everything is ok, we leave it alone
fixture.provider.removeRegistrationStateChangeListener(eventCollector);
}
/**
* This method verifies that all operation sets have the type they are
* declared to have.
*
* @throws ClassNotFoundException if a class name found in the keys for the
* supported operation sets doesn't correspond to a class that the
* class loader can find.
*/
public void testOperationsSets() throws ClassNotFoundException
{
Map supportedOperationSets =
fixture.provider.getSupportedOperationSets();
//get the keys for the supported operation set. The keys are strings
//corresponding to class names.
Iterator setNames = supportedOperationSets.keySet().iterator();
while (setNames.hasNext())
{
String key = (String) setNames.next();
Object opSet = supportedOperationSets.get(key);
assertTrue(opSet + " was not an instance of " + key +"as declared",
Class.forName(key).isInstance(opSet));
}
}
/**
* This class acts as a very simple registration listener for the protocol
* provider and simply records all events it receives and notifies
* (<code>notifyAll()</code>) all objects waiting for an instance of this
* class upon receiving an event that signals a completed registration.
*
* TODO: This class is just the same as the one in
* TestProtocolProviderServiceGibberishImpl.java . Is there any reason for
* duplicating code this way?
*
* @author Emil Ivov
* @author Mihai Balan
*/
public class RegistrationEventCollector
implements RegistrationStateChangeListener
{
/**
* We store all the received events in this list. It's made public to
* ease later inspection by unit tests.
*/
public List collectedStates = new LinkedList();
/**
* This method simply records all received events in a <code>List</code>
* that can be easily inspected by unit tests. In case we receive a
* registration event notifying us of a completed registration, the
* method calls <code>notifyAll()</code>.
*
* @param e a <code>RegistrationStateChangeEvent</code> decribing the
* status change.
*/
public void registrationStateChanged(RegistrationStateChangeEvent e)
{
logger.debug("Received a RegistrationChangeEvent: " + e.toString());
collectedStates.add(e.getNewState());
if (e.getNewState().equals(RegistrationState.REGISTERED))
{
logger.debug("We're registered. Notifying waiting threads");
synchronized(this)
{
notifyAll();
}
}
}
/**
* Blocks until an event notifying us of the awaited status change is
* received or until <code>waitFor</code> miliseconds pass, whichever
* comes first.
*
* @param waitFor the number of seconds to wait for an event. If no
* event is received, we simply return.
*/
public void waitForEvent(long waitFor)
{
logger.trace("Waiting for a RegistrationChangeEvent");
synchronized(this)
{
if (collectedStates.contains(RegistrationState.REGISTERED))
{
logger.trace("Event already received" + collectedStates);
return;
}
try {
wait(waitFor);
if (collectedStates.size() > 0)
logger.trace("Received a RegistrationStateChangeEvent.");
else
logger.trace("No registrationStateChangeEvent received"
+ " for" + waitFor + "ms.");
} catch(InterruptedException ie)
{
logger.debug("Interrupted while waiting for "
+ "a RegistrationStateChangeEvent", ie);
}
}
}
}
/**
* Dummy implementation of a <code>SecurityAuthority</code>. It simply
* returns null credentials as the RSS "authentication" protocol requires
* none.
*
* @author Mihai Balan
*/
public class NullSecurityAuthority
implements SecurityAuthority
{
public UserCredentials obtainCredentials(String realm,
UserCredentials defaultValues) {
return null;
}
}
}

@ -0,0 +1,188 @@
/*
* SIP Communicator, the OpenSource Java VoIP and Instant Messaging client.
*
* Distributable under LGPL license.
* See terms of license at gnu.org.
*/
package net.java.sip.communicator.slick.protocol.rss;
import java.net.*;
import java.io.*;
/**
* This classed is used in the automatic testing of the RSS protocol. It acts as
* a <b>very</b> simple HTTP server that can serve RSS files. It has the ability
* to simulate an update to the file, or to send an invalid file.
*
* The usual flow when using a <code>TestingServer</code> is as follows:
* <ol>
* <li>Create <code>TestingServer</code> object.</li>
* <li>Set server behaviour through calls to <code>setAtomUsage()</code> and
* <code>setServerBehaviour()</code>.</li>
* <li>Start the server with <code>start()</code>.</li>
* <li>Retrieve contents served by the server.</li>
* <li>Stop the server with <code>stop()</code>.</li>
* <li>If necessary rewind from 2.</li>
* </ol>
*
* @see setAtomUsage, setServerBehaviour, start, stop
* @author Mihai Balan
*/
public class TestingServer
{
/* Java 1.5 specific - could simplfy things a lot when the switch is decided
* enum ServerResponse
* {
* VALID, VALID_UPDATE, VALID_NEW, INVALID
* }
*/
/**
* Numeric constant specifying an invalid file to be served.
*/
public static final int INVALID = 0;
/**
* Numeric constant specifying a valid file to be served.
*/
public static final int VALID = 1;
/**
* Numeric constant specifying a valid, updated file to be served.
*/
public static final int VALID_UPDATE = 2;
/**
* Numeric constant specifying a valid, new file to be served.
*/
public static final int VALID_NEW = 3;
/**
* <code>true</code> if ATOM-like files are used, <code>false</code>
* otherwise.
*/
private boolean usesAtom;
/**
* Flag specifying the current type of file used.
*/
private int currentFile = VALID;
/**
* ServerSocket used to listen for incoming connections.
*/
private ServerSocket server = null;
/**
* Thread for responding to client requests.
*/
private TestingServerThread runner = null;
/**
* <code>true</code> if the server was successfully launched (through a call
* to <code>start()</code>, <code>false</code> otherwise.
*/
private boolean serverActive;
/**
* Public constructor. Creates the server and binds it to port 8080 of the
* loop-back address. It uses port 8080 instead of the more
* standard port 80, because on Linux machines binding on ports smaller than
* 1023 requires root privileges.
* @throws IOException in case the server cannot bind to the specified
* address/port, it throws an IOException detailing the problem.
*/
public TestingServer()
throws IOException
{
server = new ServerSocket(8080, 20,
InetAddress.getByName(null));
usesAtom = false;
serverActive = false;
currentFile = INVALID;
}
/**
* Sets whether or not to use ATOM-like files or not
* @param usesAtom <code>true</code> to serve ATOM-like files,
* <code>false</code> otherwise.
*/
public void setAtomUsage(boolean usesAtom)
{
this.usesAtom = usesAtom;
}
/**
* Accessor for the field variable <code>usesAtom</code>
* @return <code>true</code> if ATOM-like files are used, <code>false</code>
* otherwise.
*/
public boolean usesAtom()
{
return this.usesAtom;
}
/**
* Returns the current state of the server.
* @return <code>true</code> if a successful call to <code>start()</code>
* has been issued and the server hasn't yet processed any request,
* <code>false</code> otherwise.
*/
public boolean isActive()
{
return serverActive;
}
/**
* Sets the type of file the server serves.
* @param type int enum specifying the type of file.
*/
public void setServerBehaviour(int type)
{
if (type == INVALID || type == VALID || type == VALID_UPDATE
|| type == VALID_NEW )
currentFile = type;
else
currentFile = INVALID;
}
/**
* Return the type of file currently server by the server.
* @return file type.
*/
public int getServerBehaviour()
{
return currentFile;
}
/**
* Starts the listening process for incoming connections in a separate
* thread.
*/
public void start()
{
//only allow one "instance" of the server to be running at a given time
if (serverActive)
return;
//create new thread and launch
runner = new TestingServerThread(this, server);
serverActive = true;
runner.start();
}
/**
* Takes the server into an inactive state. If the listening thread is still
* running it waits for it to end.
* @throws InterruptedException
*/
public void stop() throws InterruptedException
{
//wait for listening thread to end
if (runner.isAlive())
runner.join();
//restore server state
serverActive = false;
runner = null;
}
}

@ -0,0 +1,185 @@
/*
* SIP Communicator, the OpenSource Java VoIP and Instant Messaging client.
*
* Distributable under LGPL license.
* See terms of license at gnu.org.
*/
package net.java.sip.communicator.slick.protocol.rss;
import java.net.*;
import java.io.*;
import java.util.*;
import java.text.*;
/**
* This class represents the separate thread that a <code>TestingServer</code>
* uses to listen for incoming connections.
* A reference to the object that launched the thread is also kept too in order
* to have easier access to the server settings.
*
* @author Mihai Balan
*/
public class TestingServerThread
extends Thread
{
/**
* The server that launched us.
*/
private TestingServer launcher = null;
/**
* The server's <code>ServerSocket</code>. We keep a reference to it to as
* the call to <code>ServerSocket.accept()</code> is made in the thread (us)
* and not in the server to avoid deadlocks.
*/
private ServerSocket serverSocket;
/**
* <code>Socket</code> used for network I/O.
*/
private Socket socket;
/**
* Creates a new thread for listening for connections.
* @param launcher the <code>TestingServer</code> object that created us.
* @param serverSock the <code>ServerSocket</code> used to listen for
* connections on.
*/
public TestingServerThread(TestingServer launcher, ServerSocket serverSock)
{
/* would a check for null (mainly for the launcher) and an eventual
* NullPointerException make sense here?*/
this.launcher = launcher;
this.serverSocket = serverSock;
}
/**
* Effectively launches the server thread. It starts listening for
* connections on <code>serverSocket</code>, and upon a successful request
* serves the file according to the <code>launcher</code>'s settings.
*/
public void run()
{
if (launcher.isActive())
{
try {
socket = serverSocket.accept();
BufferedReader in = new BufferedReader(
new InputStreamReader(socket.getInputStream()));
processRequest(in);
launcher.stop();
} catch (IOException e)
{
e.printStackTrace();
socket = null;
} catch (InterruptedException ie)
{
ie.printStackTrace();
}
}
}
/**
* Processes the HTTP request and initiates the sending of a response
* according to the server settings.
*
* @param in network end-point from which we read.
*
* @throws IOException
*/
public void processRequest(BufferedReader in)
throws IOException
{
String crtLine;
String httpVersion = null;
boolean gotRequest = false;
//XXX: Debug
//System.out.println("Processing request. Dump follows:");
//look for the get string and totally and blindly ignore all other
//HTTP headers
while (! "".equals(crtLine = in.readLine().trim()) && crtLine != null)
{
//XXX: Debug
//System.out.println("> " + crtLine);
if (crtLine.startsWith("GET /"))
{
gotRequest = true;
int httpPos = -1;
httpPos = crtLine.lastIndexOf(" HTTP/");
if (httpPos != -1)
httpVersion = crtLine.substring(httpPos + 1);
else
httpVersion = "HTTP/1.0";
}
}
//if no file was requested, just abort
if (! gotRequest)
return;
BufferedWriter out = new BufferedWriter(
new OutputStreamWriter(socket.getOutputStream()));
sendResponse(out, httpVersion);
}
/**
* Builds and sends the HTTP response according to the server settings.
*
* @param out the network end-point to which we write to.
* @param httpVersion textual representation of the HTTP version used.
* Should either be "HTTP/1.0" or "HTTP/1.1".
*
* @throws IOException
*/
public void sendResponse(BufferedWriter out, String httpVersion)
throws IOException
{
String content = "";
SimpleDateFormat dateFormatter =
new SimpleDateFormat("EEE, d MMM yyyy HH:mm:ss Z");
//getting output
switch (launcher.getServerBehaviour())
{
case TestingServer.INVALID:
content = launcher.usesAtom() ? FeedFactory.getAtomInvalid()
: FeedFactory.getRssInvalid();
break;
case TestingServer.VALID:
content = launcher.usesAtom() ? FeedFactory.getAtom()
: FeedFactory.getRss();
break;
case TestingServer.VALID_UPDATE:
content = launcher.usesAtom() ? FeedFactory.getAtomUpdated()
: FeedFactory.getRssUpdated();
break;
case TestingServer.VALID_NEW:
content = launcher.usesAtom() ? FeedFactory.getAtomNew()
: FeedFactory.getRssNew();
break;
}
//XXX: Debug
//System.out.println("Sending response headers...");
//building response HTTP headers
out.write(httpVersion + "200 OK\r\n");
out.write("Server: RssTestingServer/0.0.1\r\n");
out.write("Date: " + dateFormatter.format(new Date()) + "\r\n");
out.write("Content-Type: text/html; charset=utf-8\r\n");
out.write("Content-length: " + content.length() + "\r\n");
out.write("\r\n");
//outputting the file
out.write(content);
out.close();
socket.close();
socket = null;
}
}

@ -0,0 +1,12 @@
Bundle-Activator: net.java.sip.communicator.slick.protocol.rss.RssProtocolProviderServiceLick
Bundle-Name: RSS Protocol Provider Service Leveraging Implementation Compatibility Kit
Bundle-Description: A Service Leveraging Implementation Compatibility Kit for the RSS implementation of the ProtocolProvider Service
Bundle-Vendor: sip-communicator.org
Bundle-Version: 0.0.1
Import-Package: net.java.sip.communicator.service.configuration,
net.java.sip.communicator.service.configuration.event,
junit.framework,
org.osgi.framework,
net.java.sip.communicator.util,
net.java.sip.communicator.service.protocol,
net.java.sip.communicator.service.protocol.event
Loading…
Cancel
Save