EasyMockに触れる
EasyMockを使用するとモック(擬似)オブジェクトを使用したテストを行うことが
できるらしい。
また、モック(擬似)オブジェクトの目的は、インターフェースの使われ方をテストすることであり、スタブと混同するのは正しくないとのこと。ふーん。
①スタブ・・・例えば、データベース接続を伴うデータの取得処理を隠蔽し、DBの代わりに配列などでDBをシュミレートする。
また、アプリケーションの実行、ビルドを軽量化する。
②モック・・・API(インターフェース)が正しく呼び出されることを確認する。
でも、いまいち違いがピンと来ない。。。
EasyMockでも①でいうところのDBのシュミレートができそうだし・・・。
EasyMockのインストール
最新バージョン(今回はeasymock2.0)をEasyMockから取得する。
ちなみにeasymock2.0はJDK5.0が必要です。
EasyMockを使用したテストの手順
①モックオブジェクトの生成
②正常時の期待値の設定
※.モックオブジェクトへ振る舞いを記録する。
③モックテストの実施
④モックテストの検証
※.モックオブジェクトが記録した振る舞い通りに呼び出されたか検証する。
サンプルプログラム
テスト対象のプログラム
A・・・わざとResultSet#closeメソッドの呼び出しをコメントアウトしています。
package sample.easymock; import java.sql.Connection; import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Statement; import java.util.Map; public class SampleDAO { public Map selectSample(Connection con, String sql) throws SQLException { Map result = null; Statement st = con.createStatement(); ResultSet rs = st.executeQuery(sql); if(rs.next()) { result = new HashMap(); result.put("sample", rs.getString(1)); } // close()の呼び出しをコメントアウト //A // rs.close(); st.close(); return result; } }
テストプログラム
B・・・verify(rsMock) の呼び出しでAssertionErrorがthrowされる
package sample.easymock; import static org.easymock.EasyMock.createMock; import static org.easymock.EasyMock.expect; import static org.easymock.EasyMock.replay; import static org.easymock.EasyMock.verify; import java.sql.Connection; import java.sql.ResultSet; import java.sql.Statement; import junit.framework.TestCase; public class SampleDAOTest extends TestCase { private Connection conMock; private Statement stMock; private ResultSet rsMock; protected void setUp() { // ①Mockオブジェクトの生成 conMock = createMock(Connection.class); stMock = createMock(Statement.class); rsMock = createMock(ResultSet.class); } /* * Test method for 'sample.easymock.SampleDAO.selectSample(Connection, String)' */ public void testSelectSample() throws Exception { // ②期待値の設定 expect(conMock.createStatement()).andReturn(stMock); expect(stMock.executeQuery("select * from sample")).andReturn(rsMock); expect(rsMock.next()).andReturn(false); rsMock.close(); stMock.close(); replay(conMock); replay(stMock); replay(rsMock); // ③モックテストの実施 SampleDAO dao = new SampleDAO(); dao.selectSample(conMock, "select * from sample"); // ④モックテストの検証 verify(conMock); verify(stMock); verify(rsMock); // B } }
使ってみた感想としては、簡単に動的なモックオブジェクト(スタブと呼びたい・・)を
作成できてなかなか便利。
andReturnメソッドをうまく使えばやはりスタブとして利用できそう(^^;
複数回呼び出しの確認(expectLastCall().times(3))
テスト対象のプログラム
if(rs.next()) { result = new HashMap(); result.put("sample1", rs.getString(1)); result.put("sample2", rs.getString(1)); result.put("sample3", rs.getString(1)); }
テストプログラム
expect(conMock.createStatement()).andReturn(stMock); expect(stMock.executeQuery("select * from sample")).andReturn(rsMock); expect(rsMock.next()).andReturn(true); expect(rsMock.getString(1)).andReturn("hello"); expectLastCall().times(3);
Swatchのインストール(ログだけ)
yumのリポジトリファイルを追加
vi /etc/yum.repos.d/dag.repo [dag] name=Dag RPM Repository for Fedora Core baseurl=http://apt.sw.be/fedora/$releasever/en/$basearch/dag gpgcheck=1 enabled=1
yumを使用してインストール
[root@fourth tmp]# yum install swatch Setting up Install Process Setting up Repos dag 100% |=========================| 1.1 kB 00:00 base 100% |=========================| 1.1 kB 00:00 updates-released 100% |=========================| 951 B 00:00 Reading repository metadata in from local files dag : ################################################## 2860/2860 base : ################################################## 2622/2622 updates-re: ################################################## 1020/1020 Resolving Dependencies --> Populating transaction set with selected packages. Please wait. ---> Package swatch.noarch 0:3.1-1.1.fc3.rf set to be updated --> Running transaction check --> Processing Dependency: perl(Date::Calc) for package: swatch --> Processing Dependency: perl(Time::HiRes) for package: swatch --> Processing Dependency: perl(Date::Format) for package: swatch --> Processing Dependency: perl(Date::Parse) for package: swatch --> Processing Dependency: perl(Mail::Sendmail) for package: swatch --> Processing Dependency: perl(File::Tail) for package: swatch --> Restarting Dependency Resolution with new changes. --> Populating transaction set with selected packages. Please wait. ---> Package perl-File-Tail.noarch 0:0.99.1-1.1.fc3.rf set to be updated ---> Package perl-Mail-Sendmail.noarch 0:0.79-1.1.fc3.rf set to be updated ---> Package perl-Time-HiRes.i386 0:1.55-3 set to be updated ---> Package perl-TimeDate.noarch 1:1.16-2 set to be updated ---> Package perl-Date-Calc.i386 0:5.3-9 set to be updated --> Running transaction check --> Processing Dependency: perl(Bit::Vector) for package: perl-Date-Calc --> Restarting Dependency Resolution with new changes. --> Populating transaction set with selected packages. Please wait. ---> Package perl-Bit-Vector.i386 0:6.3-3 set to be updated --> Running transaction check Dependencies Resolved Transaction Listing: Install: swatch.noarch 0:3.1-1.1.fc3.rf - dag Performing the following to resolve dependencies: Install: perl-Bit-Vector.i386 0:6.3-3 - base Install: perl-Date-Calc.i386 0:5.3-9 - base Install: perl-File-Tail.noarch 0:0.99.1-1.1.fc3.rf - dag Install: perl-Mail-Sendmail.noarch 0:0.79-1.1.fc3.rf - dag Install: perl-Time-HiRes.i386 0:1.55-3 - base Install: perl-TimeDate.noarch 1:1.16-2 - base Total download size: 482 k Is this ok [y/N]: y Downloading Packages: (1/4): perl-File-Tail-0.9 100% |=========================| 21 kB 00:00 (2/4): swatch-3.1-1.1.fc3 100% |=========================| 45 kB 00:00 (3/4): perl-Mail-Sendmail 100% |=========================| 23 kB 00:00 (4/4): perl-TimeDate-1.16 100% |=========================| 31 kB 00:08 Running Transaction Test Finished Transaction Test Transaction Test Succeeded Running Transaction Installing: perl-Time-HiRes 100 % done 1/7 Installing: perl-File-Tail 100 % done 2/7 Installing: perl-TimeDate 100 % done 3/7 Installing: perl-Mail-Sendmail 100 % done 4/7 Installing: perl-Date-Calc 100 % done 5/7 Installing: swatch 100 % done 6/7 Installing: perl-Bit-Vector 100 % done 7/7 Installed: swatch.noarch 0:3.1-1.1.fc3.rf Dependency Installed: perl-Bit-Vector.i386 0:6.3-3 perl-Date-Calc.i386 0:5.3-9 perl-File-Tail.noarch 0:0.99.1-1.1.fc3.rf perl-Mail-Sendmail.noarch 0:0.79-1.1.fc3.rf perl-Time-HiRes.i386 0:1.55-3 perl-TimeDate.noarch 1:1.16-2 Complete! [root@fourth tmp]# mkdir /etc/swatch [root@fourth tmp]# vi /etc/swatch/.swatchrc watchfor /Priority\: 2/ echo=normal mail=user hoge@hoge.jp, subject=Snort Security Alert!
Swatchのインストール
眠いのでログだけ・・・
ランレベル
Fedora Core のランレベル
ランレベルとは、Linuxの動作モードのことで、ランレベルごとに
起動されるプログラムは異なります。
Linuxでは、ランレベル別のディレクトリ(/etc/rc.d/rc?.d)にある
ファイル名により、各ランレベルで実行するプログラムを指定しています。
例えば、ランレベル3の場合は/etc/rc.d/rc3.dにあるスクリプトのうち
S(Start)ではじまるスクリプトが実行され、K(Kill)で始まるスクリプト
は実行されません。
つまり、ファイル名の先頭1文字を変更することで起動するサービスを変更する
ことができるというわけです。
ちなみにKやSに続く数字は、実行されるスクリプトの優先順位をけってします。
(数字の小さいスクリプトから順に実行される。)
ランレベル | 説明 |
---|---|
0 | 停止 |
1 | シングルユーザモード |
2 | マルチユーザモード(NFS*1なし) |
3 | マルチユーザモード |
4 | 未使用 |
5 | GUIログイン(X11) |
6 | 再起動 |
ランレベルの変更はinitコマンドで行います。
ランレベルを3にする場合
# init 3
現在のランレベルの確認はrunlevelコマンドで行います。
# runlevel N 5
アクセス制限
サービスごとのアクセス制御
TCP/IPのサービスへのアクセスを制限する方法としては、「tcp_wrappers」または「xined」に
よる制限が一般的です。
tcp_wrappers
tcp_wrappersは、telnetdやftpdなどのサービスをインターネットデーモン「inetd」から起動
する場合に「/usr/sbin/tcpd」経由で起動し、「/etc/hosts.allow」および「/etc/hosts.deny」
ファイルでアクセス制限を行う為の仕組です。
xined
Fedora Coreはデフォルトでindetdによるサービスの起動を行わず、代わりにxinetdを使用する
ようになっている。
xinedを使用したアクセス制限は、「/etc/xinetd.conf」ファイル、または「/etc/xinetd.d」
ディレクトリ以下のサービスごとのファイルに記述をする。
アプリケーションのアクセス制限
アプリケーションには独自のアクセス制限機能が実装されている。
例)
Apacheの場合
httpd.confによるアクセス制限の例
SetEnvIf User-Agent "DoCoMo" com_on <Directory /var/www/html/> 〜(中略)〜 Order deny,allow Deny from all Allow from example.jp Allow from 10.1.0.0/16 Allow from 192.168.1 Allow from env=com_on </Directory>
BINDのacl
BINDの場合、「named.conf」にアクセス制限を記述することが可能。
DNSサーバの場合、ゾーンデータを転送するスレーブサーバや問い合わせを許可するコンピュータ
やネットワークを限定しておくことが重要です。
acl "internal" { 192.168.1/24; ← 内部ネットワークのリスト 192.168.2/24; }; acl "aclzone" { 10.1.xxx.xxx; ← ゾーンデータを転送するスレーブサーバのリスト 210.xxx.xxx.xxx; }; options { directory "/var/named"; allow-query { "internal" }; ← ①の内部のネットワークからの問い合わせにのみ回答する。 }; 〜(中略)〜 zone "example.co.jp" { type master; file "example.co.jp.zone"; allow-transfer { "aclzone"; }; ← ゾーンデータを転送するサーバを②のサーバに制限。 };
Linuxのセキュリティ
Linuxのセキュリティについて学んでみる。