<?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/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Yun Fu&#039;s Worklog</title>
	<atom:link href="http://www.fuyun.org/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.fuyun.org</link>
	<description>a system engineer&#039;s blog</description>
	<lastBuildDate>Fri, 09 Apr 2010 17:41:55 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.9.2</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>A CSS solution to two equal-height columns in HTML</title>
		<link>http://www.fuyun.org/2010/03/a-css-solution-to-two-euqal-height-columns/</link>
		<comments>http://www.fuyun.org/2010/03/a-css-solution-to-two-euqal-height-columns/#comments</comments>
		<pubDate>Mon, 22 Mar 2010 11:14:26 +0000</pubDate>
		<dc:creator>Yun Fu</dc:creator>
				<category><![CDATA[programming]]></category>

		<guid isPermaLink="false">http://www.fuyun.org/?p=303</guid>
		<description><![CDATA[It seems to be a very tricky problem to make two columns with equal height in HTML using CSS. There are many articles on how to do it. Maybe the most reliable way is to use Javascript to force it at the browser side since all CSS solutions look like hacks. I also found a [...]]]></description>
			<content:encoded><![CDATA[<p>It seems to be a very tricky problem to make two columns with equal height in HTML using CSS. There are many articles on how to do it. Maybe the most reliable way is to use Javascript to force it at the browser side since all CSS solutions look like hacks. I also found a possible solution using CSS.</p>
<p>The problem is like this. It is very common to create a two-column layout in CSS. Most books only cover how to make it using float and margin. It is enough if the columns have no background color or border. However, if you need to put a background color or border for the shorter column, you may find that its height is not as the same as the longer one as shown below. By default, a block&#8217;s height is determined by its content.</p>
<p style="text-align: center;"><a href="http://www.fuyun.org/wp-content/uploads/2010/03/Picture-1.png"><img class="size-medium wp-image-306 aligncenter" title="Two columns with different height" src="http://www.fuyun.org/wp-content/uploads/2010/03/Picture-3-300x183.png" alt="" width="300" height="183" /></a></p>
<p style="text-align: left;">You can see the effect <a href="http://www.fuyun.org/wp-content/uploads/2010/03/2col-test-wrong.html">here</a>. The effect is different when the DOCTYPE is XHTML or HTML. The main CSS and HTML parts are like this.</p>
<pre class="brush: xml;">
&lt;style type=&quot;text/css&quot;&gt;
#container {
    width: 500px;
}
#left_col {
    float: left;
    background-color: #573333;
    width: 150px;
}
#right_col {
    width: 350px;
    background-color: #DDD;
    margin-left: 150px;
}
&lt;/style&gt;

&lt;body&gt;
&lt;div id=&quot;container&quot;&gt;
    &lt;div id=&quot;left_col&quot;&gt;
        Left Column ...
    &lt;/div&gt;
    &lt;div id=&quot;right_col&quot;&gt;
        Right Column ...
    &lt;/div&gt;
&lt;/div&gt;
&lt;/body&gt;
</pre>
<p>The solution I found is to add &#8220;position: relative;&#8221; to the container and add &#8220;position: absolute; height: 100%;&#8221; to left_col.  Every single change counts. You must put all of them. Also, I removed &#8220;float:left&#8221; from left_col. But it is safe to keep it there. The new style is like this.</p>
<pre class="brush: xml;">
&lt;style type=&quot;text/css&quot;&gt;
#container {
    width: 500px;
    position: relative;
}
#left_col {
    background-color: #573333;
    width: 150px;
    position: absolute;
    height: 100%;
}
#right_col {
    width: 350px;
    background-color: #DDD;
    margin-left: 150px;
}
&lt;/style&gt;
</pre>
<p>Then it will render the layout as follows. You can see the effect <a href="../wp-content/uploads/2010/03/2col-test.html">here</a>.</p>
<p style="text-align: center;"><a href="http://www.fuyun.org/wp-content/uploads/2010/03/Picture-4.png"><img class="size-medium wp-image-311  aligncenter" title="Two columns with equal height" src="http://www.fuyun.org/wp-content/uploads/2010/03/Picture-4-300x183.png" alt="" width="300" height="183" /></a></p>
<p style="text-align: justify;">Why? I don&#8217;t know.I found this trick from the CSS of Yahoo Search. Yahoo search results are in 2-column layout. I found this CSS trick  is at least one of many tricks they use to force the left column to be the equal height of the right column. However, I got a theory (actually a feeling) for it. I guess, by declaring left column as position:absolute, CSS rendering somehow delays the time point to determine its final layout until other components in the container are rendered. I put Javascript at a few breakpoints in HTML to print its height. I found it is 0 after its content is rendered. Then it increases while the right column is rendered. So does the container&#8217;s height.</p>
<p style="text-align: left;">Is this a hack? I found it works on all browsers and all operating systems I can find.</p>
<p style="text-align: justify;">There is one problem with this solution. It only works when the left column is shorter than the right one. The left column will be as equal high as the right column anyway even if the right column is shorter.</p>
<p style="text-align: left;">
<p style="text-align: left;">
<p style="text-align: left;">
]]></content:encoded>
			<wfw:commentRss>http://www.fuyun.org/2010/03/a-css-solution-to-two-euqal-height-columns/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Install WinRAR on Fedora</title>
		<link>http://www.fuyun.org/2010/03/install-winrar-on-fedora/</link>
		<comments>http://www.fuyun.org/2010/03/install-winrar-on-fedora/#comments</comments>
		<pubDate>Wed, 10 Mar 2010 07:22:44 +0000</pubDate>
		<dc:creator>Yun Fu</dc:creator>
				<category><![CDATA[setup]]></category>

		<guid isPermaLink="false">http://www.fuyun.org/?p=289</guid>
		<description><![CDATA[Simply put, to install WinRar on Fedora:

rpm -ivh http://download1.rpmfusion.org/nonfree/fedora/rpmfusion-nonfree-release-stable.noarch.rpm
yum install unrar

The first command adds rpmfusion into your yum repository. Then, the yum command installs unrar from rpmfusion. Now you can extract rar files by &#8216;unrar e filename&#8217;. During the installation of unrar, yum may prompt you if it is OK to import GPG key from [...]]]></description>
			<content:encoded><![CDATA[<p>Simply put, to install WinRar on Fedora:</p>
<pre class="brush: plain;">
rpm -ivh http://download1.rpmfusion.org/nonfree/fedora/rpmfusion-nonfree-release-stable.noarch.rpm
yum install unrar
</pre>
<p>The first command adds rpmfusion into your yum repository. Then, the yum command installs unrar from rpmfusion. Now you can extract rar files by &#8216;unrar e filename&#8217;. During the installation of unrar, yum may prompt you if it is OK to import GPG key from RPM Fusion nonfree repository? Type y to add it. </p>
<p>WinRAR is provided by RARLAB. Its <a href="http://www.rarlab.com/rar_add.htm">download page</a> points to <a href="http://rpm.livna.org/">rpm.livna.org</a> for Linux version unrar. However,  livna has been merged to <a href="http://rpmfusion.org">rpmfusion</a>. Thus, you should add rpmfusion into your yum repository instead. To do that, either follow the section &#8220;command line setup using rpm&#8221; on its <a href="http://rpmfusion.org/Configuration"> config page</a> or only add the nonfree repository (WinRAR is not open sourced) as I did above. </p>
]]></content:encoded>
			<wfw:commentRss>http://www.fuyun.org/2010/03/install-winrar-on-fedora/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Install Ruby On Rails and Django on Fedora</title>
		<link>http://www.fuyun.org/2010/02/install-ruby-on-rails-and-django-on-fedora/</link>
		<comments>http://www.fuyun.org/2010/02/install-ruby-on-rails-and-django-on-fedora/#comments</comments>
		<pubDate>Tue, 16 Feb 2010 07:42:30 +0000</pubDate>
		<dc:creator>Yun Fu</dc:creator>
				<category><![CDATA[setup]]></category>

		<guid isPermaLink="false">http://www.fuyun.org/?p=278</guid>
		<description><![CDATA[Some notes about installing ruby on rails and django on fedora 11.
To install ROR on Fedora:

yum install mysql
yum install mysql-devel
yum install ruby
yum install rubygems
gem install rails
gem install mysql

Later, I found the gem installed by yum is 1.3.1, which is lower than required by rake. So I downloaded rubygems-1.3.5.tgz from http://rubyforge.org/frs/?group_id=126, and installed it by

&#62; ruby [...]]]></description>
			<content:encoded><![CDATA[<p>Some notes about installing ruby on rails and django on fedora 11.</p>
<p><strong>To install ROR on Fedora:</strong></p>
<pre class="brush: plain;">
yum install mysql
yum install mysql-devel
yum install ruby
yum install rubygems
gem install rails
gem install mysql
</pre>
<p>Later, I found the gem installed by yum is 1.3.1, which is lower than required by rake. So I downloaded rubygems-1.3.5.tgz from http://rubyforge.org/frs/?group_id=126, and installed it by</p>
<pre class="brush: plain;">
&gt; ruby setup.rb
</pre>
<p>To test the installation of mysql, write a ruby script with </p>
<pre class="brush: ruby;">
require &quot;mysql&quot;
</pre>
<p>But I got this error,</p>
<pre class="brush: plain;">
mysqltestst.rb:1:in `require': no such file to load -- mysql (LoadError)
</pre>
<p>To fix it, add environment variable  RUBYOPT=rubygems</p>
<p>Another way is as follows</p>
<pre class="brush: ruby;">
require &quot;rubygems&quot;
require &quot;mysql&quot;
</pre>
<p><strong>To install Django on Fedora:</strong></p>
<pre class="brush: plain;">
yum install Django
yum install MySQL-python.i586
</pre>
]]></content:encoded>
			<wfw:commentRss>http://www.fuyun.org/2010/02/install-ruby-on-rails-and-django-on-fedora/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Weird Boot Error: virbr0 starting userspace STP failed</title>
		<link>http://www.fuyun.org/2010/02/weird-boot-error-virbr0-starting-userspace-stp-failed/</link>
		<comments>http://www.fuyun.org/2010/02/weird-boot-error-virbr0-starting-userspace-stp-failed/#comments</comments>
		<pubDate>Tue, 02 Feb 2010 06:58:07 +0000</pubDate>
		<dc:creator>Yun Fu</dc:creator>
				<category><![CDATA[system]]></category>

		<guid isPermaLink="false">http://www.fuyun.org/?p=258</guid>
		<description><![CDATA[I suddenly could not boot my Linux box (Fedora 11) today. It showed some error messages as follows,

virbr0: starting userspace STP failed, starting kernel STP
ADDRCONF(NETDEV_UP): eth0: link is not ready
e1000e: eth0 NIC Link is Up 100 Mbps Full Duplex, Flow Control: None
0000:00:19.0: eth0: 10/100 speed: disabling TSO
ADDRCONF(NETDEV_CHANGE): eth0: link becomes ready

In the beginning, I thought [...]]]></description>
			<content:encoded><![CDATA[<p>I suddenly could not boot my Linux box (Fedora 11) today. It showed some error messages as follows,</p>
<pre class="brush: plain;">
virbr0: starting userspace STP failed, starting kernel STP
ADDRCONF(NETDEV_UP): eth0: link is not ready
e1000e: eth0 NIC Link is Up 100 Mbps Full Duplex, Flow Control: None
0000:00:19.0: eth0: 10/100 speed: disabling TSO
ADDRCONF(NETDEV_CHANGE): eth0: link becomes ready
</pre>
<p>In the beginning, I thought it is related to network or libvirtd. But I did not solve the problem by turning off libvirtd. I did not change anything in my last boot. But I updated Fedora packages using Software Update. However, I did not pay attention what I updated. By searching on web, I found some people talked about this issue after upgrading video drivers. I felt it may be the same reason.</p>
<p>My video card is Nvidia. I used nvidia linux driver (NVIDIA-Linux-x86-190.42-pkg1.run) downloaded from nvidia web site. To give it a try, I decided to reinstall it. So I boot at runlevel 3, and run the driver installer NVIDIA-Linux-x86-190.42-pkg1.run again in text mode. It rebuilt the driver and reset xorg.conf. Then, the problem was fixed.</p>
<p>After that, I found that there are actually a lot of errors in /var/log/Xorg.?.log such as</p>
<pre class="brush: plain;">
NVIDIA: Failed to load the NVIDIA kernel module. Please check
your system's kernel log for additional error messages.
</pre>
<p>Also, /var/log/messages log has error message as follows.</p>
<pre class="brush: plain;">
WARNING: GdmLocalDisplayFactory: maximum number of X display failures
reached: check X server log for errors
init:prefdm main process terminated with status 1
</pre>
<p>So this weird boot error is really caused by video driver. The errors related to virbr0 were just coincident errors that showed up after X failed to start. I checked my logs. Such errors have been there for every boot. I just did not see them. Now I turn off libvirtd service.</p>
<p>FYI, to boot into runlevel 3 in this hanging case. Select the linux image entry to boot in GRUB, press &#8216;e&#8217;.  In next screen, move to the kernel line, press &#8216;e&#8217;.  In my case, it ends up with &#8216;rhgb quiet&#8217;, which is redhat graphic boot. Delete &#8216;rhgb, quite&#8217;, replace it with &#8216;3&#8242;. Then press &#8216;b&#8217;. It will boot to runlevel 3 without starting those daemons or X window. Just log in as root and reinstall the video driver. If runlevel 3 does not work, try single user mode, i.e. replace &#8216;rhgb quite&#8217; with &#8217;single&#8217;.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.fuyun.org/2010/02/weird-boot-error-virbr0-starting-userspace-stp-failed/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Ruby MySQL adapter on Windows</title>
		<link>http://www.fuyun.org/2010/01/ruby-mysql-adapter-on-windows/</link>
		<comments>http://www.fuyun.org/2010/01/ruby-mysql-adapter-on-windows/#comments</comments>
		<pubDate>Sat, 23 Jan 2010 10:05:24 +0000</pubDate>
		<dc:creator>Yun Fu</dc:creator>
				<category><![CDATA[programming]]></category>

		<guid isPermaLink="false">http://www.fuyun.org/?p=241</guid>
		<description><![CDATA[It is very easy to install Ruby MySQL adapter using gem on Windows.

gem install mysql

But I found Ruby MySQL adapter does not work with MySQL 5.1 on my Windows box. When Ruby executed SQLs or Rails server got requests, I got some errors like this

C:/Ruby/lib/ruby/gems/1.8/gems/activerecord-2.3.5/lib/active_record/
connection_adapters/abstract_adapter.rb:39: [BUG] Segmentation fault
ruby 1.8.6 (2009-08-04) [i386-mingw32]

This application has requested the [...]]]></description>
			<content:encoded><![CDATA[<p>It is very easy to install Ruby MySQL adapter using gem on Windows.</p>
<pre class="brush: bash;">
gem install mysql
</pre>
<p>But I found Ruby MySQL adapter does not work with MySQL 5.1 on my Windows box. When Ruby executed SQLs or Rails server got requests, I got some errors like this</p>
<pre class="brush: bash;">
C:/Ruby/lib/ruby/gems/1.8/gems/activerecord-2.3.5/lib/active_record/
connection_adapters/abstract_adapter.rb:39: [BUG] Segmentation fault
ruby 1.8.6 (2009-08-04) [i386-mingw32]

This application has requested the Runtime to terminate it in an unusual way.
Please contact the application's support team for more information.
</pre>
<p>It seems the reason is that this version of mysql gem does not work with MySQL 5.1 lib. I saw some suggestions on Web to downgrade MySQL to 5.0 to solve the problem. However, I don&#8217;t want to downgrade MySQL. It turns out the solution is very simple. Download MySQL 5.0 noinstall version mysql-noinstall-5.0.89-win32.zip from <a href="http://dev.mysql.com/downloads/mysql/5.0.html">http://dev.mysql.com/downloads/mysql/5.0.html</a>. Extract libmysql.dll and copy it to C:\Ruby\bin. Then, the problem is solved. I am still running MySQL 5.1. But Ruby uses this MySQL 5.0 version dll.</p>
<p>My environment:  Ruby 1.8.6. Gem 1.3.5. MySQL gem version 2.8.1. Rails version is 2.3.5. Windows XP and MySQL 5.1.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.fuyun.org/2010/01/ruby-mysql-adapter-on-windows/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Install MySQL for Python (MySQLdb) on Windows</title>
		<link>http://www.fuyun.org/2009/12/install-mysql-for-python-on-windows/</link>
		<comments>http://www.fuyun.org/2009/12/install-mysql-for-python-on-windows/#comments</comments>
		<pubDate>Sun, 20 Dec 2009 09:38:58 +0000</pubDate>
		<dc:creator>Yun Fu</dc:creator>
				<category><![CDATA[programming]]></category>

		<guid isPermaLink="false">http://www.fuyun.org/?p=231</guid>
		<description><![CDATA[It took me quite a while to figure out how to build and install MySQL for Python (MySQLdb) on Windows. I&#8217;d better write it down.
There is no binary distribution of MySQLdb for Python 2.6 on Windows. I have to build it from the source. My environment is Windows XP. MySQL 5.1. Python 2.6 (windows version, [...]]]></description>
			<content:encoded><![CDATA[<p>It took me quite a while to figure out how to build and install <a href="http://sourceforge.net/projects/mysql-python/files/mysql-python/">MySQL for Python (MySQLdb)</a> on Windows. I&#8217;d better write it down.</p>
<p>There is no binary distribution of MySQLdb for Python 2.6 on Windows. I have to build it from the source. My environment is Windows XP. MySQL 5.1. Python 2.6 (windows version, not cygwin), and MySQL-python-1.2.3c1. Also, I have Microsoft Visual C++ 2008 Express Edition (Microsoft Visual Studio 9.0) installed, which is required to compile the C code in MySQL-python.</p>
<p>First of all, install <a href="http://pypi.python.org/pypi/setuptools">Python setuptools</a>, if you haven&#8217;t installed it. It is required in MySQL-python setup.py. I also added C:\Python26\Scripts into environment PATH, where easy_install is installed.</p>
<p>Then, make sure you have MySQL Developer Components installed. Download MySQL msi installer version, select &#8220;Developer Components&#8221; in Custom Setup. It will install C:\Program Files\MySQL\MySQL Server 5.1\include,  lib\debug and lib\opt  for you. They are not installed by default.</p>
<p>Uncompress MySQL-python-1.2.3c1.tar.gz into a directory. Open a command window (cmd), change to the directory.</p>
<p>Try to run,</p>
<p style="padding-left: 30px;"><em>setup.py build</em></p>
<p>I got this error in setup_windows.py:</p>
<p style="padding-left: 30px;"><em>in get_config<br />
serverKey = _winreg.OpenKey(_winreg.HKEY_LOCAL_MACHINE, options['registry_key'])<br />
WindowsError: [Error 2] The system cannot find the file specified</em></p>
<p>So I edited site.cfg, changed the MySQL version from 5.0 to 5.1 (since I am using 5.1)</p>
<p style="padding-left: 30px;"><em>registry_key = SOFTWARE\MySQL AB\MySQL Server 5.1</em></p>
<p>You can use regedit to check which version you are using. It is specified at: HKEY_LOCAL_MACHINE/SOFTWARE/MySQL AB/MySQL Server 5.1.</p>
<p>Now try to build it again. I got this error:</p>
<p style="padding-left: 30px;"><em>build\temp.win32-2.6\Release\_mysql.pyd.manifest : general error c1010070: Failed to load and parse the manifest. The system cannot find  the file specified.<br />
error: command &#8216;mt.exe&#8217; failed with exit status 31</em></p>
<p>To fix this problem, go to C:\Python26\Lib\distutils, edit msvc9compiler.py, search for &#8216;MANIFESTFILE&#8217;, you will find the following line</p>
<p style="padding-left: 30px;"><em>ld_args.append(&#8216;/MANIFESTFILE:&#8217; + temp_manifest)</em></p>
<p>Then append the following line after the above line,</p>
<p style="padding-left: 30px;"><em>ld_args.append(&#8216;/MANIFEST&#8217;)</em></p>
<p>Then go back to run &#8220;setup.py build&#8221;, it will succeed. Finally, run</p>
<p style="padding-left: 30px;"><em>setup.py install</em></p>
<p>Test it in python</p>
<p style="padding-left: 30px;"><em>&gt;&gt;&gt; import MySQLdb<br />
&gt;&gt;&gt;</em></p>
]]></content:encoded>
			<wfw:commentRss>http://www.fuyun.org/2009/12/install-mysql-for-python-on-windows/feed/</wfw:commentRss>
		<slash:comments>25</slash:comments>
		</item>
		<item>
		<title>Cannot open libstdc++.so.5 on fedora 11</title>
		<link>http://www.fuyun.org/2009/11/cannot-open-libstdc-so-5-on-fedora-11/</link>
		<comments>http://www.fuyun.org/2009/11/cannot-open-libstdc-so-5-on-fedora-11/#comments</comments>
		<pubDate>Wed, 18 Nov 2009 08:47:06 +0000</pubDate>
		<dc:creator>Yun Fu</dc:creator>
				<category><![CDATA[programming]]></category>

		<guid isPermaLink="false">http://www.fuyun.org/?p=228</guid>
		<description><![CDATA[I just upgraded to fedora 11. When I installed java EE SDK, I got the following error
> ./java_ee_sdk-5_07-linux-nojdk.bin
./java_ee_sdk-5_07-linux-nojdk.bin: error while loading shared libraries: libstdc++.so.5: cannot open shared object file: No such file or directory
The default libstdc++ on fedora is libstdc++.so.6 installed from libstdc++.i586. To solve the problem, install compat-libstdc++-33. For fedora 11, the package can [...]]]></description>
			<content:encoded><![CDATA[<p>I just upgraded to fedora 11. When I installed java EE SDK, I got the following error</p>
<p>> ./java_ee_sdk-5_07-linux-nojdk.bin<br />
./java_ee_sdk-5_07-linux-nojdk.bin: error while loading shared libraries: libstdc++.so.5: cannot open shared object file: No such file or directory</p>
<p>The default libstdc++ on fedora is libstdc++.so.6 installed from libstdc++.i586. To solve the problem, install compat-libstdc++-33. For fedora 11, the package can be installed by</p>
<p>> yum install compat-libstdc++-33-3.2.3-66.i586</p>
]]></content:encoded>
			<wfw:commentRss>http://www.fuyun.org/2009/11/cannot-open-libstdc-so-5-on-fedora-11/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>How to read input files in maven junit</title>
		<link>http://www.fuyun.org/2009/11/how-to-read-input-files-in-maven-junit/</link>
		<comments>http://www.fuyun.org/2009/11/how-to-read-input-files-in-maven-junit/#comments</comments>
		<pubDate>Thu, 05 Nov 2009 09:37:53 +0000</pubDate>
		<dc:creator>Yun Fu</dc:creator>
				<category><![CDATA[programming]]></category>
		<category><![CDATA[java]]></category>

		<guid isPermaLink="false">http://www.fuyun.org/?p=209</guid>
		<description><![CDATA[Sometimes we need to put unit test data into plain text files. For example, assume we want to test a parser using a json string as the test data. If we put the json string as a constant string in the java code, we end up with a lot of error-prone escaping characters. In that [...]]]></description>
			<content:encoded><![CDATA[<p>Sometimes we need to put unit test data into plain text files. For example, assume we want to test a parser using a json string as the test data. If we put the json string as a constant string in the java code, we end up with a lot of error-prone escaping characters. In that case, we may want to put the test string into a file as a resource and read the string from the file in junit. </p>
<p>In maven, we need to put the resource file in src/test/resources. Let me create a demo from scratch.</p>
<pre class="brush: plain;">
&gt; mvn archetype:create -DgroupId=org.fuyun -DartifactId=junitresdemo
&gt; find .
.
./junitresdemo
./junitresdemo/pom.xml
./junitresdemo/src
./junitresdemo/src/test
./junitresdemo/src/test/java
./junitresdemo/src/test/java/org
./junitresdemo/src/test/java/org/fuyun
./junitresdemo/src/test/java/org/fuyun/AppTest.java
./junitresdemo/src/main
./junitresdemo/src/main/java
./junitresdemo/src/main/java/org
./junitresdemo/src/main/java/org/fuyun
./junitresdemo/src/main/java/org/fuyun/App.java

&gt; cd junitresdemo
&gt; mkdir -p src/test/resources
&gt; vi src/test/resources/myres.txt
&gt; cat src/test/resources/myres.txt
test1=testdata
</pre>
<p>As you can see, I put my test data as a key-value pair in a property file. If your test data contains special characters such as escape char, you&#8217;d better handle file reading by yourself instead of using Properties as I am going to show. </p>
<p>Then I modify the automatically generated test code src/test/java/org/fuyun/AppTest.java as follows.</p>
<pre class="brush: java;">
package org.fuyun;

import junit.framework.Test;
import junit.framework.TestCase;
import junit.framework.TestSuite;

import java.io.InputStream;
import java.util.Properties;

public class AppTest extends TestCase {
    public AppTest( String testName ) {
        super( testName );
    }

    public static Test suite() {
        return new TestSuite( AppTest.class );
    }

    public void testApp() throws java.io.IOException {
        InputStream in =
            getClass().getClassLoader().getResourceAsStream(&quot;myres.txt&quot;);
        Properties p = new Properties();
        p.load(in);
        String mystr = p.getProperty(&quot;test1&quot;);
        assertEquals(&quot;testdata&quot;, mystr);
    }
}
</pre>
<p>To read the property file, we need to use getResourceAsStream. Actually this is why I want to write this blog. If you search on web, you may find that people talk about you can load the file using Class.getResourceAsStream(). So, I am supposed to write the line as</p>
<pre class="brush: java;">
        InputStream in = getClass().getResourceAsStream(&quot;myres.txt&quot;);
</pre>
<p>It can compile. But the test will fail. The InputStream variable <em>in</em> will be null, i.e., it cannot find myres.txt. Why? Why do we have to use the method defined in ClassLoader?</p>
<p>The difference between Class.getResourceAsStream and ClassLoader.getResourceAsStream is that Class.getResourceAsStream attempts to first resolve the file name by appending the package prefix (org/fuyun/) if the file name is not an absolute path, otherwise removes the leading &#8220;/&#8221; if the path is absolute. Then, it calls the ClassLoader&#8217;s getResourceAsStream to load the resolved file name. This is documented <a href="http://java.sun.com/j2se/1.5.0/docs/guide/lang/resources.html">here</a>. </p>
<p>For example, if I do the following hack, the test will pass temporarily.</p>
<pre class="brush: plain;">
&gt; mv target/test-classes/myres.txt target/test-classes/org/fuyun/.
&gt; mvn test
</pre>
<p>But to really fix it, we should revise the line by adding a leading &#8220;/&#8221; in the file name as follows.</p>
<pre class="brush: java;">
        InputStream in = getClass().getResourceAsStream(&quot;/myres.txt&quot;);
</pre>
<p>On the other hand, if you use ClassLoader.getResourceAsStream, the leading &#8220;/&#8221; will make it unable to find the file. </p>
]]></content:encoded>
			<wfw:commentRss>http://www.fuyun.org/2009/11/how-to-read-input-files-in-maven-junit/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>How to convert an integer to base64 in Python</title>
		<link>http://www.fuyun.org/2009/10/how-to-convert-an-integer-to-base64-in-python/</link>
		<comments>http://www.fuyun.org/2009/10/how-to-convert-an-integer-to-base64-in-python/#comments</comments>
		<pubDate>Tue, 27 Oct 2009 09:36:35 +0000</pubDate>
		<dc:creator>Yun Fu</dc:creator>
				<category><![CDATA[programming]]></category>
		<category><![CDATA[python]]></category>

		<guid isPermaLink="false">http://www.fuyun.org/?p=175</guid>
		<description><![CDATA[I found  a bunch of solutions on web and noticed it may lead to entirely different results if you ignore a few assumptions.
First of all, the input of base64 algorithm is an array of bytes, which is a string in Python. Thus, before converting an integer to base64, you need to convert the integer to [...]]]></description>
			<content:encoded><![CDATA[<p>I found  a bunch of solutions on web and noticed it may lead to entirely different results if you ignore a few assumptions.</p>
<p>First of all, the input of base64 algorithm is an array of bytes, which is a string in Python. Thus, before converting an integer to base64, you need to convert the integer to an array of bytes. To do so, you need to first decide the byte order: big endian or little endian. The best solution is using Python module struct. It can convert an integer to binary format in either byte order. Also, it can handle signed integers, etc.</p>
<p>I am using unsigned long long, which has 64 bits,  and little endian,  the simplest solution could be:</p>
<p>&gt;&gt;&gt;import struct</p>
<p>&gt;&gt;&gt; n = 12345</p>
<p>&gt;&gt;&gt; struct.pack(&#8216;&lt;Q&#8217;, n).encode(&#8220;base64&#8243;).strip()<br />
&#8216;OTAAAAAAAAA=&#8217;</p>
<p>However, the reason I need to use base64 here is that base64 is more compact than the decimal format of integers.  But the above example has a lot of A&#8217;s, which are caused by zeros padded in the unsigned long long. Also, I am using encode method provided by string to generate base64 in the above example. A better base64 support is module base64, which supports url safe version of base64.</p>
<p>The following example can solve these problems. Also, I remove the padding =&#8217;s here.</p>
<pre class="brush: python;">

import base64
import struct

def encode(n):
  data = struct.pack('&lt;Q', n).rstrip('\x00')
  if len(data)==0:
    data = '\x00'
  s = base64.urlsafe_b64encode(data).rstrip('=')
  return s

def decode(s):
  data = base64.urlsafe_b64decode(s + '==')
  n = struct.unpack('&lt;Q', data + '\x00'* (8-len(data)) )
  return n[0]
</pre>
<p>Notice that when stripping zeros, how to handle the integer zero itself? If we simply remove all tailing zeros, we will end up with an empty string here. Thus, I keep a byte zero if the integer is zero. In decode, we have to  pad zeros to variable data to 8 bytes for unpacking it as an unsigned long long. Notice the padding is in little endian order too.</p>
<p>Run some tests:</p>
<pre class="brush: plain;">
&gt;&gt;&gt; print encode(0)
AA

&gt;&gt;&gt; print decode('AA')
0

&gt;&gt;&gt; print encode(12345)
OTA

&gt;&gt;&gt; print decode('OTA')
12345
</pre>
<p>The code is for Python 2.5.</p>
<p>Finally, an interesting question. Is that true  any string constructed by  base64 characters is a valid base64 string?  See the following example,</p>
<pre class="brush: plain;">
&gt;&gt;&gt;print decode('100')
19927

&gt;&gt;&gt;print decode('101')
19927

&gt;&gt;&gt;print decode('102')
19927

&gt;&gt;&gt;print decode('103')
19927
</pre>
<p>The results are the same. Why? I would say only 100 is a valid base64 string. But python base64 decoder can tolerate the other 3. We know that 4 base64 chars (24 bits) represent 3 bytes. If we have only 3 base64 chars (18 bits) here, it can only represent 2 bytes (16 bits). Thus, the least significant 2 bits of the 3 chars (&#8220;101&#8243;-&#8221;102&#8243;) are ignored by base64 decoder.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.fuyun.org/2009/10/how-to-convert-an-integer-to-base64-in-python/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>glassfish errors in netbeans</title>
		<link>http://www.fuyun.org/2009/10/glassfish-errors-in-netbeans/</link>
		<comments>http://www.fuyun.org/2009/10/glassfish-errors-in-netbeans/#comments</comments>
		<pubDate>Mon, 19 Oct 2009 06:30:30 +0000</pubDate>
		<dc:creator>Yun Fu</dc:creator>
				<category><![CDATA[programming]]></category>

		<guid isPermaLink="false">http://www.fuyun.org/?p=171</guid>
		<description><![CDATA[I don&#8217;t use IDE since I am used to editing in vim. I tried to adopt eclipse for java work several times. But I just could not keep using it. However, I recently started to see if I can adopt netbeans for java ee development. My environment is netbeans + glassfish + maven.
I experienced several [...]]]></description>
			<content:encoded><![CDATA[<p>I don&#8217;t use IDE since I am used to editing in vim. I tried to adopt eclipse for java work several times. But I just could not keep using it. However, I recently started to see if I can adopt netbeans for java ee development. My environment is netbeans + glassfish + maven.</p>
<p>I experienced several problems in the beginning</p>
<p><strong>(1) NetBeans: No suitable Deployment Server is defined for the project or globally.</strong></p>
<p>I found the solution here: <a href="http://wiki.netbeans.org/JAXWSNB6Maven2GlassFishV2">http://wiki.netbeans.org/JAXWSNB6Maven2GlassFishV2</a></p>
<p>In Netbeans:</p>
<ol>
<li> Right-click the project and select <span style="font-family: monospace; white-space: pre;">Properties</span>. Navigate to the <span style="font-family: monospace; white-space: pre;">Run</span> tab.</li>
<li> In the Server field select GlassFish V2</li>
</ol>
<p><strong>(2) netbeans SEC5046: Audit: Authentication refused for [admin].</strong></p>
<p>Why do I see this error while I can still successfully deploy my application to glassfish from netbeans?</p>
<p>I found the solution here <a href="http://forums.java.net/jive/thread.jspa?threadID=35551">http://forums.java.net/jive/thread.jspa?threadID=35551</a></p>
<p>Just simply remove ~/.asadminpass</p>
]]></content:encoded>
			<wfw:commentRss>http://www.fuyun.org/2009/10/glassfish-errors-in-netbeans/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
