前回
Karma で XHR で Binary File 読み込む時の問題 / TypeScript による Alembic の読み込み 2
Karma Web-Server からの Binary File Read は危険.
XHR を利用して Karma に用意されている Web-Server から Binary File を arraybuffer を読み込むと、問題が起こる事が分かった. 実際にどういった事がおこるかは前回を参照.
さらに、前回は先頭の 1 byte が被害を受けている様に書いたが、最上位ビットが立っている全ての byte が被害にあう様だ. 状況からいって、何らかのエンコード処理を強制的に受けているっぽい. さすがにこれは場当たり的な対応では回避できないので、根本的な対応が必要になった.
XHR の宛先だけを変える.
Alembic の読み込み処理を作りたいので、Binary File を扱う部分は変えられない. 必然的に、XHR は必要になる. また、Unit Test も外せないし Karma+Jasmine+PhantomJS の組み合わせは、今実装している内容にはとても良い.
なので、現状の環境は維持しつつ、XHR に対して正しく返答してくれる先を用意する事にした. 具体的には、Karma とは別に XHR に返答してくれる Web-Server を事前にたてておき、Unit Test での XHR はそちらに送る事で、XHR で Binary File を受け取りつつ現状の Test 環境を維持できると考えた.
XHR の宛先を立てる.
現状、gulp を用いた build 環境を構築しているので、gulp で使える用途にあった module を探した. いくつか選択肢があったが、人気が高そうだった gulp-connect を使う事にした.
https://www.npmjs.com/package/gulp-connect
gulp-connect は、gulp API のコンセプトとあっていないという事から deprecated になっている様だ. 現在は gulp API にあわせて書き直された gulp-webserver というのもあるらしい.
https://www.npmjs.com/package/gulp-webserver
ただ、そもそも karma が gulp API にそっていないし、karma の現状の呼び出し方から考えると明示的に Server を止められた方が良いと思うため、今回は gulp-connect を利用している.
また、XHR に返答して貰わないといけないので、CORS (Cross-origin resource sharing) に対応している必要がある. 下記の module を利用する事で、gulp-connect でたてた Web-Server を CORS に対応させる事ができる.
https://www.npmjs.com/package/cors
gulp task を作る.
もともと、karma を起動している直前で、gulp-connect を利用して Unit Test で利用したい Binary File を管理する Web-Server をたて、全ての Test が終了したら Web-Server を落とす、という task を用意したい. 下記の様に task を書く事で実現できた.
gulp.task('test', ['compile-spec-typescript'], function(done) {
connect.server({
root: 'spec',
port: 8000,
middleware: function() {
return [cors()];
}
});
karma.server.start({
configFile: __dirname + '/karma.conf.js',
singleRun: true
}, function(exitCode) {
connect.serverClose();
done();
})
})
それぞれの module のおかげで、とても簡潔にかける. すばらしい !!
ちなみに、karma の呼び出し方が現在は非推奨な形にしているのはわざと. 推奨されている書き方だと、Test に失敗した場合に例外が発生して、それ以降の Test が何故かキャンセルされてしまう. 非推奨の形だと、ちゃんと Test 自体は継続してくれるので、こうしている….
Unit Test から XHR を送る.
http://localhost:8000 として XHR を受け取る Web-Server をたてたので、宛先をそれに合わせて書き換える. 下記の様に書く事で問題なく動作した.
describe('File read test using XMLHttpRequest', function() {
var request = new XMLHttpRequest();
beforeAll(function (done) {
request.open('GET', 'http://localhost:8000/assets/test.bin', true);
request.responseType = 'arraybuffer';
request.addEventListener('loadend', function () {
done();
});
request.send();
})
it('Read binary files?', function() {
expect(request.status).toBe(200);
expect(request.response).toEqual(jasmine.any(ArrayBuffer));
var buffer = <ArrayBuffer>request.response;
expect(buffer.byteLength).toBe(8);
})
})
現在、jasmine 2.0 を利用しているので beforeAll で XHR を発行して同期をとっているが、jasmine 1.0 の場合は runs/waitFor を使って発行する事になると思う.
上記では Test していないが、もちろん内容も正しく帰ってくるようになり、アドホックな対応も書く必要がなくなった.
という訳で
つづく…
次回こそ Alembic の中身に…. っていうか、HDF5 って凄くめんどくさい. Ogawa に完全以降してから始めれば良かったかも….