calabash/calabash-ios — pull request #350 by jmoody (2014-04-02 16:48:55+00:00)
Title: WIP relaunch compares server version with gem version

###### needs code review

Any takers? Don't be shy.

- [ ] @krukow
- [ ] @gregeng
- [ ] @jescribano
- [ ] @aroos
- [ ] @cwang

Feel free to add anyone else who might have an opinion.

## motivation

This is a WIP pull request.

Many of the problems I see on the Calabash iOS support channels are rooted in server / gem version incompatibility.

I trying to implement ways to:

* allow visual inspection of the calabash.framework for its version,
* allow command-line inspection of the calabash.framework for its version,
* allow command-line inspection of a binary for its server-version, and
* automatically test compatibility at runtime.

###### todo

- [ ] strategy for checking the server version from the calabash-ios gem (not using check)

## what is implemented so far

See the companion server PR: https://github.com/calabash/calabash-ios-server/pull/42

#### visual inspection

Added a symlink in the framework from the version to Versions/A.

```
$ tree -L 2 calabash.framework/
├── Headers -> Versions/Current/Headers
├── Resources -> Versions/Current/Resources
├── Versions
│ ├── 0.9.169 -> A
│ ├── A
│ └── Current -> A
└── calabash -> Versions/Current/calabash
```

#### command line tool

The calabash.framework now includes a command-line tool that reports its version.

```
$ calabash.framework/Resources/version => 0.9.169
```

#### compiled binary inspection

The format of the `kLPCALABASHVERSION` constant makes it possible to search a compiled binary for the calabash version.

```
$ strings Briar-cal.app/Briar-cal | grep -E 'CALABASH VERSION' | cut -d ' ' -f 3 => 0.9.169
```

#### testing compatibility at runtime

I implemented a ruby solution that checks compatibility at runtime.

If there is an app bundle (i.e. the run is against the simulator), the check is done on the app binary using the compiled binary inspection.

If there is not an app bundle (i.e. the run is against a device), the check is done agains the server. This is a weak test because compatibility cannot be checked until the server is launched, so if a compatibility problem is serious enough to prohibit the app launch, no check can be made.

To avoid expensive calls to `strings` and repeatedly pinging the server, the server version is cached in class variable `@@server_version` on the `Calabash::Cucumber::Launcher`. Since the server version cannot change at runtime, this caching is safe; we can safely check once and never again.

ATM, the version compatibility check is strict - the versions must match.

I can image introducing a `MIN_FRAMEWORK_VERSION` variable to lib/version.rb and doing greater-than/less-than checks.

Rising a error or exiting during a Before hook is not reliable, so I opted to report a warning to the user that the gem and server versions were incompatible.

```
WARN: server version is not compatible with gem version
please update your server and gem
server version: '0.9.168'
gem version: '0.9.169'
```