環境構築でよく使う Linux コマンドなど

最近、環境構築する機会があったので、よく使う Linux コマンドなどをメモる。完全に個人のメモレベルなので、いろいろ間違っている可能性あり。
尚、OS は不幸にも CentOS 5.4 ...。

アーカイブ

.tar.gz 形式のアーカイブファイルを扱う場合は tar コマンドを使う。

# tar xzvf /path/to/foobar.tar.gz // 展開する
# tar czvf /path/to/foobar.tar.gz /foo/bar // 作成する
# tar czvf /path/to/foobar.tar.gz /foo/bar -X .ignore
(.ignore に記載したパターンに一致するファイルはアーカイブに含まれない)

ポート/プロセスを調べる

あるポートがどのプログラムに使われているか調べる場合は netstat コマンドを使う。
(Java のソフトウェアを使っていると java.net.BindException: Address already in use というエラーにしばしば遭遇することがある)

# netstat -nlp
  • n : 名前解決せず、IPアドレスで表示する
  • l : LISTEN しているポートを表示する
  • p : プロセスID(PID)とプログラム名を表示する

実行中のプロセスを調べる場合は ps コマンドを使う。

# ps auxf
  • a : 自分以外のセッションのプロセスを表示する
  • u : ユーザを表示する
  • x : すべてのプロセスを表示する
  • f : プロセスの親子関係を表示する

ネットワーク関連

DHCPの環境でIPアドレスを再取得する場合は dhclient コマンドを使う。

# dhclient -r // IPアドレス解放
# dhclient // IPアドレス取得

ネットワークを再起動する場合は /etc/init.d/network を使う。

# /etc/init.d/network restart
# service network restart // 本来の使い方はたぶんこっち

SSL 関連

httpdSSL を使う場合は以下の手順で証明書を作成する。(オレオレ証明書)
OpenSSL と mod_ssl をインストールしていない場合はインストールする。

# yum install openssl
# yum install mod_ssl

証明書を作成する。

# cd /etc/httpd/conf
# openssl genrsa -aes128 1024 > server.key
// パスフレーズを入力する

# openssl req -new -key server.key > server.csr
// Common Name にはサーバのホスト/IPアドレスを設定する (他はブランクでも問題なし)

# openssl x509 -in server.csr -days 365 -req -signkey server.key > server.crt
// 365日間有効な証明書

SSL の設定

# vi /etc/httpd/conf.d/ssl.conf

  // 以下を変更する
  SSLCertificateFile /etc/httpd/conf/server.crt
  SSLCertificateKeyFile /etc/httpd/conf/server.key

# /etc/init.d/httpd restart // 再起動

(番外) CentALT から Apache HTTP Server インストールする

古い CentOS だと、新しいバージョンの httpdyum でインストールできない場合がある模様。この場合は CentALT リポジトリからインストールする。

// EPEL
# wget http://dl.fedoraproject.org/pub/epel/5/x86_64/epel-release-5-4.noarch.rpm
# rpm -ivh epel-release-5-4.noarch.rpm
// CentALT
# wget http://mirror.sysadminguide.net/centalt/repository/centos/5/x86_64/centalt-release-5-3.noarch.rpm
# rpm -ivh centalt-release-5-3.noarch.rpm

# vi /etc/yum.repos.d/centalt.repo

  // baseurl と enabled を変更
  baseurl=http://mirror.sysadminguide.net/centalt/repository/centos/5/$basearch/
  enabled=0

# yum list --enablerepo=CentALT httpd | grep CentALT // インストールするバージョンを確認する
# yum install --enablerepo=CentALT httpd

(番外) 旧バージョンの Jenkins をインストールする

不幸にも Java 6 で Jenkins を稼働させる必要がある場合は 1.607 をインストールする。
(1.608 以降は Java 7 以上が必須)

// Jenkins インストールで Error performing checksum になるのでこのパッケージをインストール
# yum -y --enablerepo=epel install python-hashlib


# wget -O /etc/yum.repos.d/jenkins.repo http://pkg.jenkins-ci.org/redhat/jenkins.repo
# wget http://pkg.jenkins-ci.org/redhat/jenkins-ci.org.key
# rpm --import jenkins-ci.org.key

# yum --showduplicates list jenkins // インストールするバージョンを確認する
# yum install jenkins-1.607-1.1

Haskell を使ってみる 4 (タプル)

前回の続き

Haskell を使ってみる 3 (リスト内包表記) - kntmr-blog

タプル

タプルは、複数の異なる型の要素を格納することができる。タプルは括弧で囲む。

Prelude> (1,3)
(1,3)
Prelude> (1,'a',"Hello")
(1,'a',"Hello")

サイズ2のタプルはペアと呼ばれる。サイズ3のタプルはトリプルと呼ばれる。タプルはサイズが固定で、ペアとトリプルは異なる型として扱われる。ペアとトリプルを混在させるとエラーになる。

Prelude> [(1,2),(4,5,6),(8,9)]

<interactive>:13:8: error:
    • Couldn't match expected type ‘(t, t1)’
                  with actual type ‘(Integer, Integer, Integer)’
    • In the expression: (4, 5, 6)
      In the expression: [(1, 2), (4, 5, 6), (8, 9)]
      In an equation for ‘it’: it = [(1, 2), (4, 5, 6), (8, 9)]
    • Relevant bindings include
        it :: [(t, t1)] (bound at <interactive>:13:1)

サイズが同じで要素の型が異なるタプルは区別される。

Prelude> [(1,2),(1,'a')]

<interactive>:15:5: error:
    • Could not deduce (Num Char) arising from the literal ‘2’
      from the context: Num t
        bound by the inferred type of it :: Num t => [(t, Char)]
        at <interactive>:15:1-15
    • In the expression: 2
      In the expression: (1, 2)
      In the expression: [(1, 2), (1, 'a')]

タプル (ペア) を操作する関数

Prelude> fst (1,2) -- 1つ目の要素を返す
1
Prelude> snd ('a', 'b') -- 2つ目の要素を返す
'b'
Prelude> zip [1,2,3] ["one","two","three"] -- 2つのリストを受け取りタプルのリストを作成する
[(1,"one"),(2,"two"),(3,"three")]

zip 関数は異なる型のリストを受け取れるため、リストのサイズが異なる場合はサイズが小さい方のリストに合わせられる。また、遅延評価なので有限リストと無限リストを zip することができる。

Prelude> zip [1,2,3,4,5] ["one","two","three"]
[(1,"one"),(2,"two"),(3,"three")]
Prelude> zip [1..] ["one","two","three"]
[(1,"one"),(2,"two"),(3,"three")]

空のタプル ()ユニットと呼ばれる。


今回はタプルのところだけ。

InputStream のカスタム Matcher

なんとなく思い付きで書いた java.io.InputStream のオレオレ Matcher です。あまり使い道はなさそう...。(単純にカスタム Matcher を書いてみたかっただけ)

InputStream を byte 配列に読み込んで Arrays.equals で比較します。読み込んだ配列をメンバに保持しているのは、単純に Description に出力したいためです。

gist.github.com

JMockit の Mock 化する方法あれこれ

JMockit で java.util.Calendar のメソッドを Mock 化する - kntmr-blog

これの続き。

以下、テスト対象クラスとして単純に文字列を連結して返すだけのクラスを用意。

public class FooService {
    BarService barService;
    public String execute(String arg) {
        return "Foo" + barService.execute(arg);
    }
}

public class BarService {
    public String execute(String arg) {
        return "Bar" + arg;
    }
}

JMockit の Expectations で Mock 化する

モック化は MockUp<T> を使う方法以外に、Expectations を使う方法がある。

FooService#execute(String) をテストする場合。

public class FooServiceTest {
    @Tested
    FooService sut;
    @Injectable
    BarService barService;
    @Test
    public void test() {
        final String expected = "FooBARBAZ";
        new Expectations() {
            {
                barService.execute(anyString); result = "BARBAZ"; times = 1; // モックの挙動と呼出しの検証
            }
        };
        String actual = sut.execute("dummy");
        assertThat(actual, is(expected));
    }
}

Expectations はモックの挙動を定義するだけではなく、メソッド呼出しを検証することができる。
上記は times = 1BarService#execute(String) が1回だけ呼ばれることを検証する。

Verifications を使うと検証の部分を Expectations から分離することができる。

public class FooServiceTest {
    @Tested
    FooService sut;
    @Injectable
    BarService barService;
    @Test
    public void test() {
        final String expected = "FooBARBAZ";
        new Expectations() {
            {
                barService.execute(anyString); result = "BARBAZ"; // モックの挙動を定義
            }
        };
        String actual = sut.execute("dummy");
        assertThat(actual, is(expected));
        new Verifications() {
            {
                barService.execute(anyString); times = 1; // 呼出しの検証
            }
        };
    }
}

モックに渡した値を検証する場合。

public class FooServiceTest {
    @Tested
    FooService sut;
    @Injectable
    BarService barService;
    @Test
    public void test() {
        sut.execute("hogehoge");
        new Verifications() {
            {
                List<String> arg = new ArrayList<String>();
                barService.execute(withCapture(arg)); times = 1;
                assertThat(arg.get(0), is("hogehoge"));
            }
        };
    }
}

withCapture でモックに渡した値をチェックすることができる。

JMockit で private メソッドを Mock 化する

以下、文字列の連結部分を private メソッドに切り出しただけのクラス。

public class FooService {
    public String execute(String arg) {
        return executeInternal(arg);
    }
    private String executeInternal(String arg) {
        return "Foo" + arg;
    }
}

FooService#executeInternal(String) をテストする場合。

public class FooServiceTest {
    @Tested
    FooService sut;
    @Test
    public void test() {
        final String expected = "FooBar";
        String actual = Deencapsulation.invoke(sut, "executeInternal", "Bar");
        assertThat(actual, is(expected));
    }
}

Deencapsulation#invoke(Object, String, Object...) にテスト対象クラスとメソッド名、パラメータを渡して private メソッドを実行する。

Haskell を使ってみる 3 (リスト内包表記)

前回の続き

Haskell を使ってみる 2 (リストの操作) - kntmr-blog

レンジ

列挙できる要素の組み合わせでリストを作成することができる。

Prelude> [1..10]
[1,2,3,4,5,6,7,8,9,10]
Prelude> ['a'..'z']
"abcdefghijklmnopqrstuvwxyz"

ステップを指定してリストを作成することができる。ステップサイズは1つしか指定できないため、等差数列ではないリストは作成できない。

Prelude> [2,4..10] -- 偶数のリスト
[2,4,6,8,10]
Prelude> [10,9..1] -- 減少列の作成が可能
[10,9,8,7,6,5,4,3,2,1]

Prelude> ['a','c'..'z'] -- 文字列のステップ指定
"acegikmoqsuwy"

レンジで上限を指定しない場合、無限リストが作成できる。Haskell は無限リスト全体をすぐに評価することはしない。(遅延評価なので)

Prelude> take 10 [0,5..] -- 無限リストのうち最初の10個の要素で構成されるリストを作成
[0,5,10,15,20,25,30,35,40,45]

cycle は指定されたリストの要素を無限に繰り返して無限リストを作成する。

Prelude> take 10 (cycle [1,2,3]) -- 無限リストのうち最初の10個の要素で構成されるリストを作成
[1,2,3,1,2,3,1,2,3,1]

repeat は指定された要素を無限に繰り返して無限リストを作成する。

Prelude> take 10 (repeat 1) -- 無限リストのうち最初の10個の要素で構成されるリストを作成
[1,1,1,1,1,1,1,1,1,1]

replicate は繰り返す回数と要素を指定してリストを作成する。

Prelude> replicate 5 1
[1,1,1,1,1]

レンジで浮動小数点を扱う場合は精度に注意する。

Prelude> [0.1,0.3..1]
[0.1,0.3,0.5,0.7,0.8999999999999999,1.0999999999999999]

リスト内包表記

[1..10] で生成したリストの各要素の値を x束縛する。| より左はリスト内包表記の出力を表す。

Prelude> take 10 [2,4..] -- 単純なリスト操作
[2,4,6,8,10,12,14,16,18,20]
Prelude> [x * 2 | x <- [1..10]] -- リスト内包表記
[2,4,6,8,10,12,14,16,18,20]

| より右には条件 (述語) を追加できる。述語でリストを間引くことをフィルタと呼ぶ。カンマ区切りで複数の述語を指定したり、複数のリストから値を取り出すことができる。

Prelude> [x * 2 | x <- [1..10], x * 2 > 10] -- 述語を指定
[12,14,16,18,20]
Prelude> [x + y | x <- [1,2,3], y <- [10,100,1000]] -- 複数のリストから値を取り出す
[11,101,1001,12,102,1002,13,103,1003]
Prelude> [x + y | x <- [1,2,3], y <- [10,100,1000], x + y > 100] -- 述語を追加
[101,1001,102,1002,103,1003]

リスト内包表記を使って length 関数を定義する。リストの要素をすべて 1 に置換して sum 関数で足し合わせる。リストから取り出した要素は使わないので _ (アンダースコア) で使い捨てる。

Prelude> length' xs = sum [1 | _ <- xs]
Prelude> length' [1,2,3,4,5]
5
Prelude> length' "Hello"
5

リスト内包表記を使って文字列をフィルタする関数を定義する。

Prelude> removeLowercase str = [c | c <- str, c `elem` ['A'..'Z']]
Prelude> removeLowercase "Hello Haskell"
"HH"

リスト内包表記の入れ子のリストを操作する。外側のリスト内包表記が出力が、別のリスト内包表記になっている。リスト内包表記の出力は何らかのリストになる。

Prelude> let xxs = [[1,2,3,4],[11,12,13,14],[21,22,23,24]]
Prelude> [[x | x <- xs, even x] | xs <- xxs]
[[2,4],[12,14],[22,24]]

今回はリスト内包表記まで。

単体テスト(ユニットテスト/UT)で考えること

単体テスト(ユニットテスト/UT)で考えることを雑に書きます。


コードを書くときはテストしやすい粒度でメソッドを分割する。

以下の場合、なにも考えないと execute 内にすべての処理を書きがち。1メソッドの処理が長くなるとテストがやり辛くなる。

これをある程度まとまりのある処理で foo, bar などにメソッドを分割して execute から呼び出すようにする。そして、foo, bar に対してテストを書くようにすればテストコードにまとまりができて構造化し易くなる。 また、分割したメソッドのアクセス修飾子はパッケージプライベートにして、テストクラスは同一のパッケージに配置する。

public void execute(String arg) {
    Hoge hoge = foo(arg);
    Fuga fuga = bar(hoge);
}

Hoge foo(String arg) {
    // ...
}

Fuga bar(Hoge hoge) {
    // ...
}

ただ、メンバーのスキルだったり開発環境の要因でテストコードが十分に準備できないことがあるかもしれないので、必ずテストコードを書くということは考えない。
(そこを無理してやろうとすると、コストが膨れ上がるリスクがある気がするので無理はしたくない)

こういうときは人手でテストすることになるが、当然自動化みたいなことはできないので観点を挙げてテストすることが重要。
状況によってはスタブなどは事前に用意する必要はある。

余談

Java ではクラスやメソッド、変数に日本語 (Unicode) が使えます。まぁ、実際に使うことはないだろうと思っていましたが、『JUnit実践入門 - 体系的に学ぶユニットテストの技法』ではメソッドが日本語で書かれています。(最初、見たときは目から鱗だった…)

日本語なら書きやすいと思って「引数に xxx を指定した場合は hoge を返すこと」のようにメソッド名を付けるわけですが、日本語ですらどんな名前を付けようか迷うことがあります。

大抵、こういう場合は処理内容が複雑になり過ぎていることがあるので、リファクタリングすることを検討します。

これはテストに限った話ではなく、普段からコードを書くときに命名に迷うことがあればどこか構造的におかしい部分がある、と考えるようにしています。

あと、割と昔から JUnitJMockit の組み合わせ使っていますが、逆に言うとこれ以外はあまり使ったことがない…。

JMockit で java.util.Calendar のメソッドを Mock 化する

必要に迫られて調べました。

以下は java.util.Calendar#getTimeInMillis の場合。

final long expected = 1234567890000L;
new MockUp<Calendar>() {
    @Mock
    public long getTimeInMillis() {
        return expected;
    }
};
long actual = Calendar.getInstance().getTimeInMillis(); // 1234567890000 が返る
assertThat(actual, is(expected));

他のメソッドも同じように Mock 化できるはず。

ちなみに

おそらく周知の事実とは思いますが、JMockitJUnit よりも先に読み込まれるように classpath を設定する必要があります。