ct_release_test

EXPERIMENTAL support for testing of upgrade.

EXPERIMENTAL support for testing of upgrade.

This is a library module containing support for test of release related activities in one or more applications. Currenty it supports upgrade only.

Configuration

In order to find version numbers of applications to upgrade from, ct_release_test needs to access and start old OTP releases. A common_test configuration file can be used for specifying the location of such releases, for example:

  %% old-rels.cfg
  {otp_releases,[{r16b,"/path/to/R16B03-1/bin/erl"},
  	       {'17',"/path/to/17.3/bin/erl"}]}.

The configuration file should preferably point out the latest patch level on each major release.

If no such configuration file is given, init/1 will return {skip,Reason} and any attempt at running upgrade/4 will fail.

Callback functions

The following functions should be exported from a ct_release_test callback module.

All callback functions are called on the node where the upgrade is executed.

Module:upgrade_init(CtData,State) -> NewState

Types:

CtData = ct_data()
State = NewState = cb_state()

Initialyze system before upgrade test starts.

This function is called before the upgrade is started. All applications given in upgrade/4 are already started by the boot script, so this callback is intended for additional initialization, if necessary.

CtData is an opaque data structure which shall be used in any call to ct_release_test inside the callback.

Example:

  upgrade_init(CtData,State) ->
      {ok,{FromVsn,ToVsn}} = ct_release_test:get_app_vsns(CtData,myapp),
      open_connection(State).

Module:upgrade_upgraded(CtData,State) -> NewState

Types:

CtData = ct_data()
State = NewState = cb_state()

Check that upgrade was successful.

This function is called after the release_handler has successfully unpacked and installed the new release, and it has been made permanent. It allows application specific checks to ensure that the upgrade was successful.

CtData is an opaque data structure which shall be used in any call to ct_release_test inside the callback.

Example:

  upgrade_upgraded(CtData,State) ->
      check_connection_still_open(State).

Module:upgrade_downgraded(CtData,State) -> NewState

Types:

CtData = ct_data()
State = NewState = cb_state()

Check that downgrade was successful.

This function is called after the release_handler has successfully re-installed the original release, and it has been made permanent. It allows application specific checks to ensure that the downgrade was successful.

CtData is an opaque data structure which shall be used in any call to ct_release_test inside the callback.

Example:

  upgrade_downgraded(CtData,State) ->
      check_connection_closed(State).

Types


cb_state() = term()

config() = [{atom(), term()}]

ct_data()

Functions


init(Config) -> Result

  • Config = config()
  • Result = config() | SkipOrFail
  • SkipOrFail = {skip, Reason} | {fail, Reason}

Initialize ct_release_test.

This function can be called from any of the init_per_* functions in the test suite. It updates the given Config with data that will be used by future calls to other functions in this module. The returned configuration must therefore also be returned from the calling init_per_*.

If the initialization fails, e.g. if a required release can not be found, the function returns {skip,Reason}. In this case the other test support functions in this mudule can not be used.

Example:

  init_per_suite(Config) ->
      ct_release_test:init(Config).

upgrade(App, Level, Callback, Config) -> any()

  • App = atom()
  • Level = minor | major
  • Callback = {module(), InitState}
  • InitState = cb_state()
  • Config = config()

Test upgrade of the given application(s).

This function can be called from a test case. It requires that Config has been initialized by calling init/1 prior to this, for example from init_per_suite/1.

Upgrade tests are performed as follows:

Figure out which OTP release to test upgrade from. Start a node running that release and find the application versions on that node. Terminate the node. Figure out all dependencies for the applications under test. Create a release containing the core applications kernel, stdlib and sasl in addition to the application(s) under test and all dependencies of these. The versions of the applications under test will be the ones found on the OTP release to upgrade from. The versions of all other applications will be those found on the current node, i.e. the common_test node. This is the "From"-release. Create another release containing the same applications as in the previous step, but with all application versions taken from the current node. This is the "To"-release. Install the "From"-release and start a new node running this release. Perform the upgrade test and allow customized control by using callbacks: Callback: upgrade_init/2 Unpack the new release Install the new release Callback: upgrade_upgraded/2 Install the original release Callback: upgrade_downgraded/2

App or Apps specifies the applications under test, i.e. the applications which shall be upgraded. All other applications that are included have the same releases in the "From"- and "To"-releases and will therefore not be upgraded.

Level specifies which OTP release to pick the "From" versions from.

major

From verions are picked from the previous major release. For example, if the test is run on an OTP-17 node, ct_release_test will pick the application "From" versions from an OTP installation running OTP R16B.

minor

From verions are picked from the current major release. For example, if the test is run on an OTP-17 node, ct_release_test will pick the application "From" versions from an OTP installation running an earlier patch level of OTP-17.

The application "To" versions are allways picked from the current node, i.e. the common_test node.

Callback specifies the module (normally the test suite) which implements the Callback functions, and the initial value of the State variable used in these functions.

Config is the input argument received in the test case function.

Example:

  minor_upgrade(Config) ->
      ct_release_test:upgrade(ssl,minor,{?MODULE,[]},Config).

cleanup(Config) -> Result

  • Config = config()
  • Result = config()

Clean up after tests.

This function shall be called from the end_per_* function complementing the init_per_* function where init/1 is called.

It cleans up after the test, for example kills hanging nodes.

Example:

  end_per_suite(Config) ->
      ct_release_test:cleanup(Config).

get_app_vsns(CtData, App) -> {ok, {From, To}} | {error, Reason}

  • CtData = ct_data()
  • App = atom()
  • From = string()
  • To = string()
  • Reason = {app_not_found, App}

Get versions involved in this upgrade for the given application.

This function can be called from inside any of the callback functions. It returns the old (From) and new (To) versions involved in the upgrade/downgrade test for the given application.

CtData must be the first argument received in the calling callback function - an opaque data structure set by ct_release_tests.

get_appup(CtData, App) -> {ok, Appup} | {error, Reason}

  • CtData = ct_data()
  • App = atom()
  • Appup = {From, To, Up, Down}
  • From = string()
  • To = string()
  • Up = [Instr]
  • Down = [Instr]
  • Instr = term()
  • Reason = {app_not_found, App} | {vsn_not_found, {App, From}}

Get appup instructions for the given application.

This function can be called from inside any of the callback functions. It reads the appup file for the given application and returns the instructions for upgrade and downgrade for the versions in the test.

CtData must be the first argument received in the calling callback function - an opaque data structure set by ct_release_tests.

See reference manual for appup files for types definitions for the instructions.