Commit Graph

42 Commits

Author SHA1 Message Date
Pau Espin 386b78d8b0 Require OsmoMgw in OsmoBsc and update tests
Since Change-Id Ia2882b7ca31a3219c676986e85045fa08a425d7a, osmo-bsc
uses osmo-mgw and utilizes libosmo-mgcp-client to talk to it.

This commit fixes latest constant failures in voice suite.

Change-Id: I1dadd781a357fce33e7bde55e4bcbdaeb4633359
2017-11-09 13:06:03 +01:00
Pau Espin 6cdd2fdf61 Rename module ofono_client as modem
Change-Id: I43b51ae937d87d6d4e18caea59f9366e2e28c9f2
2017-11-08 10:12:07 +00:00
Pau Espin 0bcc074caf test.py: Remove unused parameter ofono_client in setup()
Change-Id: Ib8983421a7ca5f94fe1363768a12fff63c1fc64a
2017-11-08 10:12:07 +00:00
Pau Espin 4ccce7c963 Use unique incrementing value for BTS CellId
Change-Id: If4559b945a3e71f3a36fd7ac760cb094278f6b39
2017-11-08 10:05:41 +00:00
Pau Espin 5e0c251c6c Use unique incrementing value for BTS LAC
Change-Id: I9f864bac05e39ec2fc305f774194799c3d8fe1b0
2017-11-08 10:05:41 +00:00
Pau Espin 0b30279c2f Replicate resources based on times attr before combine time
As suite.conf and scenarios need to match 1-to-1 in lists, it's important to
extend the dictionaries by replicating the objects with a 'times' values
higher than 1 in order to match the objects correctly.

Since dictionanries are expanded at combine time, there's no need to
expand them during reserve() time because they are already expanded.
As a result, this commit reworks the kind of schema applied in each
place (and takes the change to start validating scenario files, which
were neglected previously).

Two unit tests are added as a show case. Unfortunately output showing
scenario dictionaries needs to be ignored while verifying because it was
encountered that different versions of python print dictionary elements
in different order.

Change-Id: I25eb639c7e3cf3b4c67a205422808bffbdd791e6
2017-09-16 19:51:33 +00:00
Pau Espin 15aae98cf0 Use tmpdir to create bts pcu-socket
In commit 329b6f4 pcu-socket path was moved to run inside the test run
dir to avoid issues between different tests creating a socket in the
same place.

However, it seems unix sockets paths are limited to 108 bytes (with Null
char included). In some cases, the run dir for a test can be quite long,
as it contains suite name, test name, etc. and the path can be longer
that the limit defined above.

In order to fix this issue, create a tmp dir using mkdtemp to ensure the
path to be used for the pcu-socket doesn't collide between different
instances of osmo-bts-trx.

Clean up of tmp dir and pcu socket is done inside the cleanup() method
called by suite.py.

method pcu_socket_path() is added to help with new implementation, and
it will be used as well as a public API later soon to be used by OsmoPcu
classes.

Related: OS#2507

Change-Id: I0c53a0a3ccc5eb2823265fe14c0f7b8f4adb1038
2017-09-12 14:42:09 +00:00
Pau Espin ac9c1bb32f esme: Add cleanup function to avoid cascade failure of tests
In commit 6100b629e5 I assumed esme
already had a cleanup function, which doesn't seem to be the case. This
means if a test calls esme.connect() and fails afterwards without
calling esme.disconnect(), the connection will be kept but as the test
will finish and the NITB is closed, then the connection will be kept
forever in an erroneous state. With the cleanup function we ensure we
will close the connection after the test.

Change-Id: Ia3a23bb8bbccfe7ac5c544521b5566164609f0a5
2017-08-10 10:59:43 +02:00
Pau Espin 6100b629e5 suite: Don't stop cleanup of objects on cleanup exception
Let's accept that during cleanup time some stuff may not be in a good
state, specially in case of a failure, but let's keep harder to clean
up everything as much as possible.

This should fix an issue in which after a test failure using an esme object,
an smpp connection is kept in a buggy state and never removed/cleaned up, and
makes all tests after it fail too because the conn is triggered at
poll() time:

   File "/home/jenkins/workspace/osmo-gsm-tester_run/osmo-gsm-tester/src/osmo_gsm_tester/suite.py", line 260, in run_tests
    self.objects_cleanup()
   File "/home/jenkins/workspace/osmo-gsm-tester_run/osmo-gsm-tester/src/osmo_gsm_tester/suite.py", line 199, in objects_cleanup
    obj.cleanup()
   File "/home/jenkins/workspace/osmo-gsm-tester_run/osmo-gsm-tester/src/osmo_gsm_tester/ofono_client.py", line 345, in cleanup
    self.dbus.cleanup()
   File "/home/jenkins/workspace/osmo-gsm-tester_run/osmo-gsm-tester/src/osmo_gsm_tester/ofono_client.py", line 170, in cleanup
    self.set_powered(False)
   File "/home/jenkins/workspace/osmo-gsm-tester_run/osmo-gsm-tester/src/osmo_gsm_tester/ofono_client.py", line 304, in set_powered
    self.set_bool('Powered', powered)
   File "/home/jenkins/workspace/osmo-gsm-tester_run/osmo-gsm-tester/src/osmo_gsm_tester/ofono_client.py", line 295, in set_bool
    event_loop.poll()
   File "/home/jenkins/workspace/osmo-gsm-tester_run/osmo-gsm-tester/src/osmo_gsm_tester/event_loop.py", line 39, in poll
    func()
   File "/home/jenkins/workspace/osmo-gsm-tester_run/osmo-gsm-tester/src/osmo_gsm_tester/esme.py", line 78, in poll
    self.client.poll()
   File "/usr/local/lib/python3.4/dist-packages/smpplib/client.py", line 321, in poll
    self.read_once(ignore_error_codes)
   File "/usr/local/lib/python3.4/dist-packages/smpplib/client.py", line 279, in read_once
    p = self.read_pdu()
   File "/usr/local/lib/python3.4/dist-packages/smpplib/client.py", line 206, in read_pdu
    raise exceptions.ConnectionError()
 smpplib.exceptions.ConnectionError

Change-Id: Ie7ef9284490f12f5cfd76c35b33b57eefab20eb6
2017-07-31 18:19:08 +02:00
Pau Espin 800a697297 suite: Print process ending prematurely
Change-Id: Icec476ccc536611f771dcc7872f5190bbd0572e7
2017-07-03 18:34:09 +02:00
Pau Espin 90c23cc991 suite: Use event_loop.poll in interactive poll
This way we also poll dbus events from ofono_client

Change-Id: I06fe9a78d702ebb05c4ece78e14fcae9e2e74ee2
2017-07-03 13:12:41 +02:00
Pau Espin 2d16f6fd2c Add support for SMPP testing
As defined in [1], the different related actors are implemented in this
commit: ESME and SMSC.

SMSC: In Osmocom, the SMSC is currently implemented inside the NITB or
the MSC. A new Smsc abstract class is created to shared code between the
NITB and the MSC, and also makes it easier for later when the SMSC is
splitted. ESMEs can be dynamically added to its configuration in a
similar way to how the BTSs are added.

ESME: A new class Esme is created which can be used by tests to control
an ESME to interact with the SMSC. The ESME functionalities are
implemented using python-smpplib. Required version of this library is at
least 43cc6f819ec76b2c0a9d36d1d439308634716227, which contains support
for python 3 and some required features to poll the socket.

This commit already contains a few tests which checks different
features and tests the API. Extending tested features or scenarios can be
later done quite easily.

The tests are not enabled by default right now, because there are several
of them in a suite and the ip_address resources are not freed after every
tests which ends up in the suite failing due to missing reserved
resources. All the tests run alone work though. When the issue is fixed
they can then be added to the default list of tests to be run.

[1] http://opensmpp.org/specs/SMPP_v3_4_Issue1_2.pdf

Change-Id: I14ca3cb009d6d646a449ca99b0200da12085c0da
2017-06-18 08:48:09 +00:00
Pau Espin 1dd2955cb1 Unuse resources after every test
Fix bug in put_all(). That method was unused before this commit.

Clean the process list after the processes are stopped,
otherwise the suite eventually fails with a 'process terminated
prematurely' error. Before it was not necessary because it was not
reused (a new suite run was created).

Change-Id: Iee12866045145544076c6c18786e1a54f18fc293
2017-06-17 17:01:20 +00:00
Pau Espin d091233934 Use a subdir of run_dir for each test
Processes created have the scope of the test, so we should store
everything in a per-suite_run/per-test directory, otherwise everything
is stored in the same trial run_dir directory and it's really messy.

Change-Id: I06be2dd21710e14c1337d13b1fe6c2f68f037957
2017-06-17 16:10:04 +00:00
Neels Hofmeyr d28d1a789e cosmetic: dbg log fix in suite.py
Change-Id: I0ff92bc1aa05bf5020bbb3b6965cbb22f1ca4d61
2017-06-14 02:59:55 +02:00
Neels Hofmeyr 38b051c6da aoip: add osmo-stp, now required for aoip runs
Change-Id: I35d4cb0d173eec240bccc1f3a5965a774b7b3506
2017-06-13 15:28:31 +00:00
Neels Hofmeyr 1a7a3f0e43 fix and refactor logging: drop 'with', simplify
With the recent fix of the junit report related issues, another issue arose:
the 'with log.Origin' was changed to disallow __enter__ing an object twice to
fix problems, now still code would fail because it tries to do 'with' on the
same object twice. The only reason is to ensure that logging is associated with
a given object. Instead of complicating even more, implement differently.

Refactor logging to simplify use: drop the 'with Origin' style completely, and
instead use the python stack to determine which objects are created by which,
and which object to associate a log statement with.

The new way: we rely on the convention that each class instance has a local
'self' referencing the object instance. If we need to find an origin as a new
object's parent, or to associate a log message with, we traverse each stack
frame, fetching the first local 'self' object that is a log.Origin class
instance.

How to use:

Simply call log.log() anywhere, and it finds an Origin object to log for, from
the stack. Alternatively call self.log() for any Origin() object to skip the
lookup.

Create classes as child class of log.Origin and make sure to call
super().__init__(category, name). This constructor will magically find a parent
Origin on the stack.

When an exception happens, we first escalate the exception up through call
scopes to where ever it is handled by log.log_exn(). This then finds an Origin
object in the traceback's stack frames, no need to nest in 'with' scopes.

Hence the 'with log.Origin' now "happens implicitly", we can write pure natural
python code, no more hassles with scope ordering.

Furthermore, any frame can place additional logging information in a frame by
calling log.ctx(). This is automatically inserted in the ancestry associated
with a log statement / exception.

Change-Id: I5f9b53150f2bb6fa9d63ce27f0806f0ca6a45e90
2017-06-13 13:32:01 +02:00
Neels Hofmeyr f8e6186406 junit result: also write for aborted runs
Even if aborted due to signal, write a JUnit report XML, and make sure to
indicate the runs as erratic.

Change-Id: I7a334ef3463896c543c0fe592d3903c15e67d4c4
2017-06-12 11:34:44 +00:00
Neels Hofmeyr 6ccda11a98 refactor: fix error handling; fix log.Origin; only one trial
A bit of refactoring to fix logging and error reporting, and simplify the code.
This transmogrifies some of the things committed in
0ffb414406 "Add JUnit XML reports; refactor test
reporting", which did not fully match the code structuring ideas used in
osmo-gsm-tester. Also solve some problems present from the start of the code
base.

Though this is a bit of a code bomb, it would take a lot of time to separate
this into smaller bits: these changes are closely related and resulted
incrementally from testing error handling and logging details. I hope it's ok.

Things changed / problems fixed:

Allow only a single trial to be run per cmdline invocation: unbloat trial and
suite invocation in osmo-gsm-tester.py.

There is a SuiteDefinition, intended to be immutable, and a mutable SuiteRun.
SuiteDefinition had a list of tests, which was modified by the SuiteRun to
record test results. Instead, have only the test basenames in the
SuiteDefinition and create a new set of Test() instances for each SuiteRun, to
ensure that no state leaks between separate suite runs.

State leaking across runs can be seen in
http://jenkins.osmocom.org/jenkins/view/osmo-gsm-tester/job/osmo-gsm-tester_run/453/
where an earlier sms test for sysmo succeeds, but its state gets overwritten by
the later sms test for trx that fails. The end result is that both tests
failed, although the first run was successful.

Fix a problem with Origin: log.Origin allowed to be __enter__ed more than once,
skipping the second entry. The problem there is that we'd still __exit__ twice
or more, popping the Origin off the stack even though it should still remain.
We could count __enter__ recurrences, but instead, completely disallow entering
a second time.

A code path should have one 'with' statement per object, at pivotal points like
run_suites or run_tests. Individual utility functions should not do 'with' on a
central object. The structure needed is, in pseudo code:

  try:
    with trial:
      try:
        with suite_run:
	  try:
	    with test:
	      test_actions()

The 'with' needs to be inside the 'try', so that the exception can be handled
in __exit__ before it reaches the exception logging.

To clarify this, like test exceptions caught in Test.run(), also move suite
exception handling from Trial into SuiteRun.run_tests(). There are 'with self'
in Test.run() and SuiteRun.run_tests(), which are well placed, because these
are pivotal points in the main code path.

Log output: clearly separate logging of distinct suites and test scripts, by
adding more large_separator() calls at the start of each test. Place these
separator calls in more logical places. Add separator size and spacing args.

Log output: print tracebacks only once, for the test script where they happen.

Have less state that duplicates other state: drop SuiteRun.test_failed_ctr and
suite.test_skipped_ctr, instead add SuiteRun.count_test_results().

For test failure reporting, store the traceback text in a separate member var.

In the text report, apply above changes and unclutter to achieve a brief and
easy to read result overview: print less filler characters, drop the starting
times, drop the tracebacks. This can be found in the individual test logs.
Because the tracebacks are no longer in the text report, the suite_test.py can
just print the reports and expect that output instead of asserting individual
contents.

In the text report, print duration in precision of .1 seconds.

Add origin information and a traceback text to the junit XML result to give
more context when browsing the result XML. For 'AssertionError', add the source
line of where the assertion hit.

Drop the explicit Failure exception. We don't need one specific exception to
mark a failure, instead any arbitrary exception is treated as a failure. Use
the exception's class name as fail_type.

Though my original idea was to use raising exceptions as the only way to cause
a test failure, I'm keeping the set_fail() function as an alternative way,
because it allows test specific cleanup and may come in handy later. To have
both ways integrate seamlessly, shift some result setting into 'finally'
clauses and make sure higher levels (suite, trial) count the contained items'
stati.

Minor tweak: write the 'pass' and 'skip' reports in lower case so that the
'FAIL' stands out.

Minor tweak: pass the return code that the program exit should return further
outward, so that the exit(1) call does not cause a SystemExit exception to be
logged.

The aims of this patch are:
- Logs are readable so that it is clear which logging belongs to which test and
  suite.
- The logging origins are correct (vs. parents gone missing as previously)
- A single test error does not cause following tests or suites to be skipped.
- An exception "above" Exception, i.e. SystemExit and the like, *does*
  immediately abort all tests and suites, and the results for tests that were
  not run are reported as "unknown" (rather than skipped on purpose):
  - Raising a SystemExit aborts all.
  - Hitting ctrl-c aborts all.
- The resulting summary in the log is brief and readable.

Change-Id: Ibf0846d457cab26f54c25e6906a8bb304724e2d8
2017-06-09 00:35:20 +02:00
Neels Hofmeyr b902b29912 test API: allow passing resource requirements
For all those API functions that directly use reserved_resources.get(), add a
'specifics' argument to be able to pick specific resources. For example, this
allows to pick a suite.bts(specifics={'type': 'osmo-bts-sysmo'})

I needed this to test error reporting for over-using resources, but will most
probably make sense in the future.

Change-Id: If6f175f4bb53dec5306fb3c6479202a7bf1c7116
2017-06-07 18:04:13 +00:00
Harald Welte 2720534f27 Re-License under GPLv3-or-later instead of AGPLv3-or-later
The "Affero" nature makes sense for the Osmocom network components like
BSC, SGSN, etc. as they are typically operated to provide a network
service.

For testing, this doesn't make so much sense as it is difficult to
imagine people creating a business out of offering to run test cases on
an end-to-end Osmocom GSM network.  So let's drop the 'Affero' here.

All code is so far developed by sysmocom staff, so as Managing Director
of sysmocom I can effect such a license change unilaterally.

Change-Id: I8959c2d605854ffdc21cb29c0fe0e715685c4c05
2017-06-03 14:23:51 +00:00
Neels Hofmeyr 4d688c2faf fix multi-suite runs: implement modem cleanup
After a suite was done, the modem object would linger. If two suites were run
consecutively, the first suite's modem objects would still log incoming SMS.

Add an object cleanup mechanism in the SuiteRun class. Start by adding a
cleanup() to the Modem object and subscribing created modems there.

Move the modem_obj() function into SuiteRun, there is no use of it being
separate, and it makes for better logging.

Change-Id: I0048d33e661d683a263c98128cd5c38b8d897dab
2017-05-29 04:32:13 +02:00
Neels Hofmeyr ed4e528693 fix: free resources when a suite run is done
Add missing code to free resources, not upon program exit, but when a suite is
done.

This allows running more than one suite in a row.

Also add a check to not attempt to free if there is nothing to be freed, to
avoid a regression test failure triggered when a suite exits without reserving
anything.

Change-Id: Ic017a1cf07052f5e48812c8553fba6f972d280f0
Related: OS#2301
2017-05-29 03:03:39 +02:00
Neels Hofmeyr 798e592fd6 MSC+BSC: add test api to run OsmoMSC and OsmoBSC with AoIP
Change-Id: I5842e8f1cba8e8e6bedfc08540efcafe207159cb
2017-05-29 00:19:45 +02:00
Neels Hofmeyr 76d8103bfb rename resource nitb_iface to ip_address
I would like to use the IP addresses also for OsmoBSC processes, so it is more
than clear now that 'nitb_iface' was the wrong naming choice.

The only distinction we may need in the future is public versus loopback
interface. To add that, we may add a trait to the 'ip_address' resource
like:

  ip_address:
  - addr: 10.42.42.1
    type: public
  - addr: 127.0.0.1
    type: loopback

This way we can substitute public vs loopback addresses flexibly (e.g. using
scenarios).

Change-Id: I3ad583ae7a33f7a7bb56fe78a125f73c56a0e860
2017-05-29 00:18:43 +02:00
Neels Hofmeyr 2d1d561eeb resource error logging that is easier to understand
Log what a suite requested, what it has reserved and the complete resource
state.

Change-Id: Ic6887bbe5fe74a73f0e344cd4078dd7ed989cc15
2017-05-29 00:18:42 +02:00
Pau Espin 927344b4dc event_loop: Create a global event loop to poll and wait for events
Tweaked-by: nhofmeyr
Change-Id: Iaa78bae0f053496377609b24a11ebaef3fd77598
2017-05-25 17:25:09 +00:00
Pau Espin 374e8a0b26 suite.py: Fix typo in variable name used during exception
Fixes a possible double exception introduced in 0ffb4144

Change-Id: I44a30f51c23e6a57ccae3483c806c0ed25d2ecf9
2017-05-22 17:52:09 +02:00
Pau Espin 469316fae0 Handle termination signals to exit gracefully and prevent resource leak
Make sure we free the reserved resources and kill launched subprocesses
before stopping. Before this patch it was not the case for instance if we
received a SIGTREM signal from kill.

Change-Id: I039e4d1908a04bf606b101ddc6a186ba67e6178e
2017-05-19 14:40:18 +02:00
Pau Espin 0ffb414406 Add JUnit XML reports; refactor test reporting
* Add Junit output file support
* Differentiate between an expected failure test and an error in the
test, as described in JUnit.
* In case of an error/exception during test, record and attach it to the
Test object and continue running the tests, and show it at the end
during the trial report.

Change-Id: Iedf6d912b3cce3333a187a4ac6d5c6b70fe9d5c5
2017-05-19 14:22:39 +02:00
Neels Hofmeyr 7e2e8f1d65 log state dir
On the log output, clearly show which state dir is used. Since all runs should
use the same state dir, this is important and/or reassuring to see.

Change-Id: Ie92f1879a35d8bb399ee916b7ef72f9ee7d47409
2017-05-15 12:22:35 +00:00
Pau Espin ecf107983b suite: Terminate processes in LIFO order
Usually the first process we started is the one we want to stay until
the end.

Change-Id: I08ea01a42af68191a659fdf8173e3fec9b1e1cfd
2017-05-08 16:57:53 +02:00
Neels Hofmeyr a88b0c7424 propagate Timeout class to test scope, use in debug suite
Change-Id: Idad34fe799bc8b8e03d773898473773656b005bd
2017-05-08 13:06:58 +02:00
Neels Hofmeyr 1ffc3fed6b on timeout, raise dedicated Timeout exception
Change-Id: I085a52194dde0f5e6dd845ffde1197f7dc83b306
2017-05-08 13:06:58 +02:00
Neels Hofmeyr acf0c937e7 fix prompt()
The prompt() is useful for supervisor (user) interaction during tests.

However it had numerous problems:
- closed stdin, so second prompt() didn't work
- no editing
- no utf-8 multichar
- unflexible poll interval (poll often to stay responsive to input)
and unrelated:
- stdin was hijacked by subprocess.Popen

Firstly pass stdin=PIPE to all subprocesses to leave the tester's stdin
untouched.

Secondly use python input() to read the user entry (instead of mucking about
with the stdin fd), and import readline for history and editing features.

The old approach was put in place to allow polling DBus and processes
regularly. Instead, allow this by running input() in a separate thread while
polling regularly and slowly in the main thread.

The prompt code is now simpler, cleaner and works better.
Will be used in the upcoming 'debug' suite.

Change-Id: I580aca52cd038b59418055259d0d09e9aab49124
2017-05-08 10:10:03 +00:00
Neels Hofmeyr f2d279c621 suite.py: add function to get several modems in a list
Will be used in the upcoming 'debug' suite.

Change-Id: Ia1156f523cff18196c88604ce3079b9532187427
2017-05-08 10:10:03 +00:00
Neels Hofmeyr c86ab211c9 fix resource error reporting for unavailable resource
On failure to find an unused resource (in case a test tries to use more
resources than are reserved), the handling code had a bug: print
reserved_resources from the proper source, i.e. suite_run.

Change-Id: Ifdc4201581b3293605196292339e841543ea284e
2017-05-06 23:07:42 +00:00
Your Name 44af3415a5 fix octphy, fix conf, improve logging
Clearly separate the kinds of BTS hardware the GSM tester knows ('type') from
the NITB's bts/type config item ('osmobsc_bts_type' -- not 'osmonitb_...' to
stay in tune with future developments: it is the libbsc that needs this).

For BTS hardware kinds, use the full name of the binary for osmo driven models:
osmo-bts-sysmo, osmo-bts-trx, osmo-bts-octphy.

Change-Id: I1aa9b48e74013a93f9db1a34730f17717fb3b36c
2017-04-13 03:39:07 +02:00
Neels Hofmeyr 5356d0adce trying to get sysmobts to work and various details
I know that these commit messages aren't very good, but the code is not stable
yet, so I'm not bothering with details.

Change-Id: I2d5e5f4a5407725d71093cbd71ef97b271eb8197
2017-04-10 05:09:23 +02:00
Neels Hofmeyr 85eb324165 make prematurely exited processes fail the test
Change-Id: I54394c40718b44378df597e32003742059052869
2017-04-09 22:01:16 +02:00
Neels Hofmeyr 3531a192ae core implementation
code bomb implementing the bulk of the osmo-gsm-tester

Change-Id: I53610becbf643ed51b90cfd9debc6992fe211ec9
2017-04-08 15:43:19 +02:00
Neels Hofmeyr dae3d3c479 initial import
The original osmo-gsm-tester was an internal development at sysmocom, mostly by
D. Laszlo Sitzer <dlsitzer@sysmocom.de>, of which this public osmo-gsm-tester
is a refactoring / rewrite.

This imports an early state of the refactoring and is not functional yet. Bits
from the earlier osmo-gsm-tester will be added as needed. The earlier commit
history is not imported.
2017-03-28 12:37:17 +02:00