1. 11 Dec, 2020 1 commit
    • Kirill Smelkov's avatar
      tests: Don't try to access db.storage when automatically closing connections · fd6b5252
      Kirill Smelkov authored
      DB.close() does `del self.storage`.
      
      https://github.com/zopefoundation/ZODB/blob/5.6.0-14-g0eae10cd0/src/ZODB/DB.py#L646
      
      This way if DB was closed, but some conn(s) were not, it will crash in
      teardown as e.g. below:
      
          _____________ ERROR at teardown of test_bigfile_zblk1_zdata_reuse ______________
      
              def teardown_module():
          >       testdb.teardown()
      
          bigfile/tests/test_filezodb.py:58:
          _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
      
          self = <wendelin.lib.testing.TestDB_ZEO object at 0x7fb9c0216350>
      
              def teardown(self):
                  # close connections that test code forgot to close
                  for connref, tb in self.connv:
                      conn = connref()
                      if conn is None:
                          continue
                      if not conn.opened:
                          continue    # still alive, but closed
                      print("W: testdb: teardown: %s left not closed by test code"
                            "; opened by:\n%s" % (conn, tb), file=sys.stderr)
      
                      db = conn.db()
          >           stor = db.storage
          E           AttributeError: 'DB' object has no attribute 'storage'
      
          lib/testing.py:217: AttributeError
      
      The fix is simple - don't use db.storage at all, because it is not actually used in that code.
      fd6b5252
  2. 18 Dec, 2019 1 commit
    • Kirill Smelkov's avatar
      tests: Keep ZEO test database on /tmp/ · 70c998c1
      Kirill Smelkov authored
      We already keep FileStorage test database on /tmp/ and NEO itself (via
      neo.tests.functional.NEOCluster) also keeps test data on tmpfs. However
      test database for ZEO was created in current directory and was wearing
      out SSD unnecessarily.
      
      FIXME zeo_forker currently does not provide API to keep all server files
      in particular place. This way server conf and log are still emitted in
      current directory, but at least we move data.fs away. Since conf and log
      are uniquely named, e.g. server-<ΧΧΧ>.conf and tmpYYY.log, and it was
      only that Data.fs was named non-uniquely, by moving Data.fs into unique
      per-server place, this also helps with-ZEO tests to execute correctly in
      parallel with `tox -p`.
      70c998c1
  3. 17 Apr, 2018 1 commit
    • Kirill Smelkov's avatar
      tests: Force-close ZODB connections in teardown, that testing code forgot to explicitly close · 5a5ed2c7
      Kirill Smelkov authored
      If a test forgets to explicitly close ZODB connection it was using, this
      connection stays alive in transaction synchronizers (it is a weakset),
      and continues to be used on e.g. transaction.commit() when all
      synchronizers are invoked. This could lead to crashes like below when
      underlying ZODB storage was closed by test module teardown and testing
      moved on to another test module:
      
          $ WENDELIN_CORE_TEST_DB="<neo>" py.test  bigfile/tests/test_filezodb.py::test_bigfile_zblk1_zdata_reuse lib/tests/test_zodb.py
          ======= test session starts ========
          platform linux2 -- Python 2.7.14+, pytest-3.5.0, py-1.5.3, pluggy-0.6.0
          rootdir: /home/kirr/src/wendelin/wendelin.core, inifile:
          collected 2 items
      
          bigfile/tests/test_filezodb.py .                                     [ 50%]
          lib/tests/test_zodb.py F                                             [100%]
      
          ______ test_deactivate_btree _______
      
              def test_deactivate_btree():
                  root = dbopen()
                  # init btree with many leaf nodes
                  leafv = []
                  root['btree'] = B = IOBTree()
                  for i in range(10000):
                      B[i] = xi = XInt(i)
                      leafv.append(xi)
          >       transaction.commit()
      
          lib/tests/test_zodb.py:56:
          _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
          ../venv/z5/local/lib/python2.7/site-packages/transaction/_manager.py:131: in commit
              return self.get().commit()
          ../venv/z5/local/lib/python2.7/site-packages/transaction/_transaction.py:316: in commit
              self._synchronizers.map(lambda s: s.afterCompletion(self))
          ../venv/z5/local/lib/python2.7/site-packages/transaction/weakset.py:62: in map
              f(elt)
          ../venv/z5/local/lib/python2.7/site-packages/transaction/_transaction.py:316: in <lambda>
              self._synchronizers.map(lambda s: s.afterCompletion(self))
          ../venv/z5/local/lib/python2.7/site-packages/ZODB/Connection.py:757: in afterCompletion
              self.newTransaction(transaction, False)
          ../venv/z5/local/lib/python2.7/site-packages/ZODB/Connection.py:737: in newTransaction
              invalidated = self._storage.poll_invalidations()
          ../venv/z5/local/lib/python2.7/site-packages/ZODB/mvccadapter.py:131: in poll_invalidations
              self._start = p64(u64(self._storage.lastTransaction()) + 1)
          _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
      
          self = <neo.client.Storage.Storage object at 0x7ffa1be8d410>
      
              def lastTransaction(self):
                  # Used in ZODB unit tests
          >       return self.app.last_tid
          E       AttributeError: 'NoneType' object has no attribute 'last_tid'
      
          ../../neo/src/lab.nexedi.com/kirr/neo/neo/client/Storage.py:181: AttributeError
      
      where NEO's Storage.app is None because the storage was closed.
      
      ----
      
      To avoid such kind of failures make sure TestDB.teardown() always closes
      all ZODB connections that were ever opened via TestDB.dbopen().
      
      Add a warning about such force-closing with information about corresponding
      connection and code place that created it, so that it is easy to
      understand which test needs a fix.
      
      /suggested-by @jm
      5a5ed2c7
  4. 16 Apr, 2018 1 commit
    • Kirill Smelkov's avatar
      tests: Teach to run with ZEO5 · 808b59b7
      Kirill Smelkov authored
      Since 7fc4ec66 (tests: Allow to test with ZEO & NEO ZODB storages) we
      can run the tests with either FileStorage, ZEO or NEO. But ZEO test
      adapter started to fail with ZEO5:
      
      	self = <wendelin.lib.testing.TestDB_ZEO object at 0x7f1feb5091d0>
      
      	    def setup(self):
      	        port  = self.zeo_forker.get_port()
      	        zconf = self.zeo_forker.ZEOConfig(('', port))
      	        self.addr, self.adminaddr, self.pid, self.path = \
      	>               self.zeo_forker.start_zeo_server(zeo_conf=zconf, port=port)
      	E       ValueError: need more than 2 values to unpack
      
      This is because in ZEO5 forker.start_zeo_server() was reworked to return only
      addr and stop closure instead of returning all details and relying on caller to
      implement stop itself.
      
      Adapt the test to detect ZEO5 and use new calling convention.
      808b59b7
  5. 24 Oct, 2017 1 commit
    • Kirill Smelkov's avatar
      Relicense to GPLv3+ with wide exception for all Free Software / Open Source... · f11386a4
      Kirill Smelkov authored
      Relicense to GPLv3+ with wide exception for all Free Software / Open Source projects + Business options.
      
      Nexedi stack is licensed under Free Software licenses with various exceptions
      that cover three business cases:
      
      - Free Software
      - Proprietary Software
      - Rebranding
      
      As long as one intends to develop Free Software based on Nexedi stack, no
      license cost is involved. Developing proprietary software based on Nexedi stack
      may require a proprietary exception license. Rebranding Nexedi stack is
      prohibited unless rebranding license is acquired.
      
      Through this licensing approach, Nexedi expects to encourage Free Software
      development without restrictions and at the same time create a framework for
      proprietary software to contribute to the long term sustainability of the
      Nexedi stack.
      
      Please see https://www.nexedi.com/licensing for details, rationale and options.
      f11386a4
  6. 26 Jun, 2015 1 commit
    • Kirill Smelkov's avatar
      tests: Allow to test with ZEO & NEO ZODB storages · 7fc4ec66
      Kirill Smelkov authored
      Previously we were always testing with DBs backed up by FileStorage. Now
      we provide a way to run the testsuite with user selected storage
      backend:
      
          $ WENDELIN_CORE_TEST_DB="<fs>"   make test.py     # test with temporary db with FileStorage
          $ WENDELIN_CORE_TEST_DB="<zeo>"  make test.py     # ----------//---------- with ZEO
          $ WENDELIN_CORE_TEST_DB="<neo>"  make test.py     # ----------//---------- with NEO
      
          $ WENDELIN_CORE_TEST_DB=neo://db@master  make test.py     # test with externally provided DB
      
      Default is still to run tests with FileStorage.
      
      /cc @jm
      7fc4ec66
  7. 03 Apr, 2015 1 commit
    • Kirill Smelkov's avatar
      bigfile: Basic benchmarks · bb9d8bf1
      Kirill Smelkov authored
          - for virtual memory subsytem
          - for ZBigFiles
      
      They are not currently great, e.g. for virtmem we have in-kernel
      overhead of page clearing - in perf profiles, for bigfile_mmap compared
      to file_read kernel's clear_page_c raises significantly.
      
      That is the worker for clearing page memory and we currently cannot
      avoid that - any memory obtained from kernel (MAP_ANONYMOUS, mmap(file)
      with hole, etc...) comes pre-initialized to zeros to userspace.
      
      This can be seen in the benchmarks as well: file_readbig differs from
      file_read in only that the latter uses 1 small buffer and the first
      allocates large memory (cleared by kernel + python does the memset).
      
          bigfile/tests/bench_virtmem.py@125::bench_file_mmap_adler32     0.47  (0.86 0.49 0.47)
          bigfile/tests/bench_virtmem.py@126::bench_file_read_adler32     0.69  (1.11 0.71 0.69)
          bigfile/tests/bench_virtmem.py@127::bench_file_readbig_adler32  1.41  (1.70 1.42 1.41)
          bigfile/tests/bench_virtmem.py@128::bench_bigfile_mmap_adler32  1.42  (1.45 1.42 1.51)
      
          bigfile/tests/bench_virtmem.py@130::bench_file_mmap_md5         1.52  (1.91 1.54 1.52)
          bigfile/tests/bench_virtmem.py@131::bench_file_read_md5         1.73  (2.10 1.75 1.73)
          bigfile/tests/bench_virtmem.py@132::bench_file_readbig_md5      2.44  (2.73 2.46 2.44)
          bigfile/tests/bench_virtmem.py@133::bench_bigfile_mmap_md5      2.40  (2.48 2.40 2.53)
      
      There is MAP_UNINITIALIZED which works only for non-mmu targets and only
      if explicitly allowed when configuring kernel (off by default).
      
      There were patches to disable that pages zeroing, as it gives
      significant speedup for people's workloads, e.g. [1,2] but all of them
      did not got merged for security reasons.
      
      [1] http://marc.info/?t=132691315900001&r=1&w=2
      [2] http://thread.gmane.org/gmane.linux.kernel/548926
      
      ~~~~
      
      For ZBigFile - it is the storage who is dominating in profiles.
      bb9d8bf1