#!/usr/bin/python3 # Copyright 2023 Weber Yann # # This file is part of rpnifs. # # geneifs is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # geneifs is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with geneifs. If not, see . # import copy import pickle import sys import unittest try: import pyrpn except (ImportError, NameError) as e: print("Error importing pyrpn. Try to run make.", file=sys.stderr) raise e ## TODO : move this function somewhere or implement it in C def decode_state(state): """ Return a dict containing rpn state dump fields """ res = dict() res['real_sz'] = len(state) res['total_sz'] = int.from_bytes(state[0:8], byteorder="little") res['argc'] = int.from_bytes(state[8:16], byteorder="little") res['stack_sz_bytes'] = state[16:24] res['stack_sz'] = state[16] res['token_sz'] = int.from_bytes(state[24:32], byteorder="little", signed=True) res['stack'] = [int.from_bytes(state[i:i+8], byteorder="little") for i in range(32, 32 + (8*res['stack_sz']),8)] res['tokens_off'] = 32 + (8*res['stack_sz']) res['tokens_real_sz'] = res['real_sz'] - res['tokens_off'] res['tokens'] = [state[i:i+24] for i in range(res['tokens_off'], res['tokens_off'] + (24*res['token_sz']), 24)] return res class TestRpnExprState(unittest.TestCase): """ Testing RPNExpr "state" related methods (__copy__, __get/setstate__) """ def test_pickle_state(self): """ Testing pickling/unpickling """ e = pyrpn.RPNExpr('0x42 + A0', 2) e2 = pickle.loads(pickle.dumps(e)) ds_e = decode_state(e.__getstate__()) ds_e2 = decode_state(e2.__getstate__()) self.assertEqual(e.__getstate__(), e2.__getstate__(), msg="EXPR: %r != %r (%r != %r)" % (e, e2, ds_e, ds_e2)) for i in range(100): e = pyrpn.RPNExpr(pyrpn.random_expr(0), 2) e.mutate(n_mutations=15); e2 = pickle.loads(pickle.dumps(e)) self.assertEqual(e.__getstate__(), e2.__getstate__(), msg="EXPR#%d : %r != %r" % (i,e, e2)) e3 = pickle.loads(pickle.dumps(e2)) self.assertEqual(e.__getstate__(), e3.__getstate__(), msg=e) self.assertEqual(e2.__getstate__(), e3.__getstate__(), msg=e) def test_copy(self): """ Basic copy test based on pickling """ e = pyrpn.RPNExpr('0x42 + A0', 2) e2 = copy.copy(e) ds_e = decode_state(e.__getstate__()) ds_e2 = decode_state(e2.__getstate__()) self.assertEqual(e.__getstate__(), e2.__getstate__(), msg="EXPR: %r != %r (%r != %r)" % (e, e2, ds_e, ds_e2)) for i in range(100): e = pyrpn.RPNExpr(pyrpn.random_expr(0), 2) e2 = copy.copy(e) self.assertEqual(e.__getstate__(), e2.__getstate__(), msg="EXPR#%d : %r != %r" % (i,e, e2)) e3 = pickle.loads(pickle.dumps(e2)) self.assertEqual(e.__getstate__(), e3.__getstate__(), msg=e) self.assertEqual(e2.__getstate__(), e3.__getstate__(), msg=e) if __name__ == '__main__': unittest.main()