Пример #1
0
def test_fullpath():
    filepath1 = 'some/path/file1.exa'
    filepath2 = 'file2.exb'
    filepath3 = 'file3'
    filepath4 = 'file4.ext'

    file1 = File(filepath1)
    assert file1.name == 'file1'
    assert file1.path == 'some/path'
    assert file1.ext == 'exa'
    assert file1.fullpath == filepath1

    file2 = File(filepath2)
    assert file2.name == 'file2'
    assert file2.path == ''
    assert file2.ext == 'exb'
    assert file2.fullpath == filepath2

    file3 = File(filepath3)
    assert file3.name == 'file3'
    assert file3.path == ''
    assert file3.ext == ''
    assert file3.fullpath == filepath3

    file4 = File(filepath4)
    assert file4.name == 'file4'
    assert file4.path == ''
    assert file4.ext == 'ext'
    assert file4.fullpath == filepath4
Пример #2
0
def test_more_than_one_dot():
    file_2dots = File('file.ex.t')
    assert file_2dots.name == 'file.ex'
    assert file_2dots.ext == 't'

    file_3dots = File('path/file.e.x.t')
    assert file_3dots.name == 'file.e.x'
    assert file_3dots.ext == 't'
Пример #3
0
def test_add_same_relation(mocker):
    mocker.patch.object(GitPython, 'IsGitRepo', return_value=True)
    mocker.patch.object(GitPython, 'CurrentBranch', return_value='master')
    repo1 = Repository('some/path/terrame')
    sys1 = System('terrame', repo1)
    f1 = File('Cell.lua')
    src1 = SourceFile(f1)
    op1 = Operation('Cell', src1)
    src1.add_code_element(op1)

    f2 = File('CellularSpace.lua')
    src2 = SourceFile(f2)
    op2 = Operation('CellularSpace', src2)
    src2.add_code_element(op2)

    sys1.add_source_file(src1)
    sys1.add_source_file(src2)

    repo2 = Repository('some/path/ca')
    sys2 = System('ca', repo2)
    f3 = File('Anneal.lua')
    src3 = SourceFile(f3)
    c1 = Call('Cell', src3)
    src3.add_code_element(c1)
    c2 = Call('CellularSpace', src3)
    src3.add_code_element(c2)

    sys2.add_source_file(src3)

    ecosystem = Ecosystem()

    tme_author = Author(Person('TerraMe Dev', '*****@*****.**'))
    ca_author = Author(Person('CA Dev', '*****@*****.**'))
    mocker.patch.object(op1, 'author', return_value=tme_author, autospec=True)
    mocker.patch.object(op2, 'author', return_value=tme_author, autospec=True)
    mocker.patch.object(c1, 'author', return_value=ca_author, autospec=True)
    mocker.patch.object(c2, 'author', return_value=ca_author, autospec=True)

    to_info = RelationInfo(sys1, src1, op1)
    from_info = FromRelationInfo(sys2, src3, c1, 10)

    rel1 = Relationship(from_info, to_info)
    rel2 = Relationship(from_info, to_info)

    assert rel1.from_system == rel2.from_system
    assert rel1.to_system == rel2.to_system
    assert rel1.from_code_element == rel2.from_code_element
    assert rel1.to_code_element == rel2.to_code_element

    ecosystem.add_relationship(rel1)
    ecosystem.add_relationship(rel2)

    assert len(ecosystem.relationships) == 2
    ecosystem.relationships[0] == rel1
    ecosystem.relationships[1] == rel2
Пример #4
0
def test_add_file_same_fullpath(mocker):
	mocker.patch.object(GitPython, 'IsGitRepo', return_value=True)
	mocker.patch.object(GitPython, 'CurrentBranch', return_value='master')
	repo = Repository('repo/terrame')
	sys = System('terrame', repo)

	file1 = File('path/file.ext')
	file2 = File('path/file.ext')
	sys.add_file(file1)

	with pytest.raises(Exception) as e:
		sys.add_file(file2)
	assert (('File \'path/file.ext\' is already present')
			in str(e.value))		
Пример #5
0
def test_add_same_code_element():
	db_url = 'postgresql://*****:*****@localhost:5432/src_add_same'	
	db = SQLAlchemyORM(db_url)
	db.create_all(True)

	filepath = 'some/path/file.src'
	file = File(filepath)
	src_file = SourceFile(file)

	f1 = Operation('get', src_file)
	src_file.add_code_element(f1)

	session = db.create_session()
	session.add(src_file)
	session.commit()	

	src_filedb = session.query(SourceFile).one()
	f2 = Operation('get', src_filedb)

	with pytest.raises(Exception) as e:
		src_filedb.add_code_element(f2)
	assert (('Code element \'get\' of type \'Operation\' is already present')
			in str(e.value))
	session.close()
	db.drop_all()	 	
Пример #6
0
def test_add_source_file():
    db_url = 'postgresql://*****:*****@localhost:5432/sys_add_src_file'
    db = SQLAlchemyORM(db_url)
    db.create_all(True)

    repo = Repository('repo/terrame')
    sys = System('terrame', repo)

    session = db.create_session()
    session.add(repo)
    session.add(sys)

    file1 = File('path/file1.ext')
    src1 = SourceFile(file1)
    sys.add_source_file(src1)

    session.commit()

    sysdb = session.query(System).get(1)
    src1db = sysdb.get_source_file(file1.fullpath)
    assert src1db.file.fullpath == src1.file.fullpath
    assert src1db.ext == src1.file.ext

    session.close()
    db.drop_all()
Пример #7
0
def test_crud():
	# create
	repo = Repository('repo/terrame')
	# sys = System('terrame', repo)
	commit_info = CommitInfo('hashhashhash')
	commit_info.date = datetime.datetime(2019, 2, 6, 14, 14, 55)  
	commit_info.msg = 'commit message'
	commit_info.author_name = 'author'
	commit_info.author_email = '*****@*****.**'	
	author = Author(Person(commit_info.author_name, commit_info.author_email), repo)
	commit = Commit(commit_info, author, repo)
	modinfo = ModificationInfo('some/path/file.ext')
	modinfo.old_path = ''
	modinfo.new_path = 'some/path/file.ext'
	modinfo.added = 10
	modinfo.removed = 0
	modinfo.type = 'ADD'
	file = File(modinfo.filename)
	mod = Modification(modinfo, file, commit)	

	assert mod.id is None
	
	session = db.create_session()
	session.add(commit)
	session.commit()

	assert mod.id is not None

	# read	
	commitdb = session.query(Commit).get(1)
	assert commitdb.msg == commit_info.msg
	assert commitdb.date.strftime('%Y-%m-%d %H:%M:%S') == '2019-02-06 14:14:55'
	assert commitdb.hash == commit_info.hash
	assert commitdb.repository.path == repo.path
	assert commitdb.author.name == commit_info.author_name
	assert commitdb.author.email == commit_info.author_email

	# update
	commit.msg = 'updating message'
	session.commit()	
	commitdb = session.query(Commit).get(1)
	assert commitdb.msg == commit.msg

	# delete
	session.delete(commit)
	session.commit()
	commitdb = session.query(Commit).get(1)
	moddb = session.query(Modification).get(1)
	repodb = session.query(Repository).get(1)
	authordb = session.query(Author).get(1)
	filedb = session.query(File).get(1)
	assert commitdb is None
	assert moddb is None
	assert repodb.path == repo.path 
	assert authordb.email == author.email
	assert filedb.id == 1 == file.id

	session.close()
	db.drop_all()
Пример #8
0
def test_dot_at_begin():
    file1 = File('.file')
    assert file1.name == '.file'
    assert file1.ext == ''
    assert file1.fullpath == '.file'

    file2 = File('path/.file.ext')
    assert file2.name == '.file'
    assert file2.ext == 'ext'
    assert file2.path == 'path'
    assert file2.fullpath == 'path/.file.ext'

    file3 = File('some/path/.file.e.x.t')
    assert file3.name == '.file.e.x'
    assert file3.ext == 't'
    assert file3.path == 'some/path'
    assert file3.fullpath == 'some/path/.file.e.x.t'
Пример #9
0
def test_operation_exists():
	filepath = 'some/path/file.src'
	file = File(filepath)
	src_file = SourceFile(file)

	f1 = Operation('get', src_file)
	src_file.add_code_element(f1)	

	assert src_file.code_element_exists(f1)
Пример #10
0
def test_crud():
    # create
    repo = Repository('repo/terrame')
    # sys = System('terrame', repo)
    commit_info = CommitInfo('hashhashhash')
    commit_info.date = datetime.datetime(2019, 2, 6, 14, 14, 55)
    commit_info.msg = 'commit message'
    commit_info.author_name = 'author'
    commit_info.author_email = '*****@*****.**'
    author = Author(Person(commit_info.author_name, commit_info.author_email))
    commit = Commit(commit_info, author, repo)
    modinfo = ModificationInfo('some/path/file.ext')
    modinfo.old_path = ''
    modinfo.new_path = 'some/path/file.ext'
    modinfo.added = 10
    modinfo.removed = 0
    modinfo.status = 'ADD'
    file = File(modinfo.filename)
    mod = Modification(modinfo, file, commit)

    session = db.create_session()
    session.add(mod)
    session.commit()

    # read
    moddb = session.query(Modification).get(1)
    assert moddb.new_path == 'some/path/file.ext'
    assert moddb.old_path == ''
    assert moddb.added == 10
    assert moddb.removed == 0
    assert moddb.status == 'ADD'
    assert moddb.commit_id == 1
    assert moddb.file_id == 1

    # update
    mod.status = 'DELETED'
    session.commit()
    moddb = session.query(Modification).get(1)
    assert moddb.status == 'DELETED'

    # delete
    session.delete(mod)
    session.commit()
    moddb = session.query(Modification).get(1)
    commitdb = session.query(Commit).get(1)
    repodb = session.query(Repository).get(1)
    authordb = session.query(Author).get(1)
    filedb = session.query(File).get(1)
    assert moddb is None
    assert commitdb.id == 1
    assert repodb.id == 1
    assert authordb.id == 1
    assert filedb.id == 1

    session.close()
    db.drop_all()
Пример #11
0
def test_number_of_calls():
    luafile = os.path.join(os.path.dirname(__file__), '../data',
                           'CellularSpace1.lua')
    file = File(luafile)
    src_file = SourceFile(file)
    src = open(luafile).read()
    analyzer = StaticAnalyzer()
    assert analyzer.number_of_calls(src_file, src, 'forEachCell') == 16
    assert analyzer.number_of_calls(src_file, src, 'addNeighborhood') == 8
    assert analyzer.number_of_calls(src_file, src, 'Cell') == 2
Пример #12
0
def test_file_exists(mocker):
	mocker.patch.object(GitPython, 'IsGitRepo', return_value=True)
	mocker.patch.object(GitPython, 'CurrentBranch', return_value='master')
	repo = Repository('repo/terrame')
	sys = System('terrame', repo)

	file = File('path/file.ext')
	sys.add_file(file)	

	assert sys.file_exists(file.fullpath)
Пример #13
0
def test_add_operation_same_name():
	filepath = 'some/path/file.src'
	file = File(filepath)
	src_file = SourceFile(file)

	f1 = Operation('get', src_file)
	src_file.add_code_element(f1)

	with pytest.raises(Exception) as e:
		src_file.add_code_element(f1)
	assert (('Code element \'get\' of type \'Operation\' is already present')
			in str(e.value))		
Пример #14
0
def test_source_file_crud():
	db_url = 'postgresql://*****:*****@localhost:5432/src_file_crud'
	db = SQLAlchemyORM(db_url)
	db.create_all(True)

	# create
	filepath = 'some/path/file.src'
	file = File(filepath)
	src_file = SourceFile(file)
	f1 = Operation('get', src_file)
	f2 = Operation('add', src_file)
	c1 = Call('call', src_file)	
	src_file.add_code_element(f1)
	src_file.add_code_element(f2)
	src_file.add_code_element(c1)

	session = db.create_session()
	session.add(file)
	session.commit()

	# read
	src_filedb = session.query(SourceFile).get(1)
	assert src_filedb.file_id == file.id
	assert src_filedb.file.ext == file.ext
	assert src_filedb.code_element_by_key(f1.key)
	assert src_filedb.code_element_by_key(f2.key)
	assert src_filedb.code_element_by_key(c1.key)

	# update
	file.ext = 'crs'
	f3 = Operation('update', src_file)
	session.add(f3)
	session.commit()
	src_filedb = session.query(SourceFile).get(1)
	code_elements = session.query(Operation).filter_by(source_file_id=src_filedb.id).all()	
	assert src_filedb.file.ext == file.ext
	assert len(code_elements) == 3

	# delete
	session.delete(src_file)
	session.commit()
	src_filedb = session.query(SourceFile).get(1)
	filedb = session.query(File).get(1)
	funcsdb = session.query(Operation).all()
	assert src_filedb is None
	assert filedb.name == 'file'
	assert len(funcsdb) == 0

	session.close()
	db.drop_all()
Пример #15
0
def test_file_crud():
	db_url = 'postgresql://*****:*****@localhost:5432/file_crud'
	db = SQLAlchemyORM(db_url)
	db.create_all(True)

	# create
	filepath = 'some/path/file.ext'
	file = File(filepath)
	assert file.name == 'file'
	assert file.path == 'some/path'
	assert file.ext == 'ext'
	assert file.fullpath == filepath

	session = db.create_session()	
	session.add(file)
	session.commit()

	# read	
	filedb = session.query(File).get(1)
	assert filedb.name == file.name
	assert filedb.path == file.path
	assert filedb.ext == file.ext
	assert filedb.fullpath == file.fullpath

	# update
	file.name = 'renamed_file'
	assert file.fullpath == 'some/path/renamed_file.ext'
	file.path = 'new/path'
	assert file.fullpath == 'new/path/renamed_file.ext'
	file.ext = 'txe'
	assert file.fullpath == 'new/path/renamed_file.txe'
	file.fullpath = 'new/full/path/renamed_file.txe'	
	assert file.fullpath == 'new/full/path/renamed_file.txe'
	session.commit()	
	filedb = session.query(File).get(1)
	assert filedb.fullpath == file.fullpath
	assert filedb.name == file.name

	# delete
	session.delete(file)
	session.commit()
	filedb = session.query(File).get(1)
	assert filedb is None

	session.close()
	db.drop_all()
Пример #16
0
def test_call_crud():
    db_url = 'postgresql://*****:*****@localhost:5432/call_crud'
    db = SQLAlchemyORM(db_url)
    db.create_all(True)

    # create
    filepath = 'some/path/file.src'
    file = File(filepath)
    src_file = SourceFile(file)
    f1 = Call('get', src_file)
    f2 = Call('add', src_file)

    session = db.create_session()
    session.add(src_file)
    session.commit()

    # read
    funcsdb = session.query(Call).all()
    assert len(funcsdb) == 2
    assert funcsdb[0].name == 'get'
    assert funcsdb[0].type == 'call'
    assert funcsdb[1].name == 'add'

    # update
    f1.name = 'getX'
    session.commit()
    f1db = session.query(Call).get(1)
    assert f1db.name == 'getX'

    # delete
    session.delete(f1)
    session.commit()
    funcsdb = session.query(Call).all()
    assert len(funcsdb) == 1
    session.delete(f2)
    session.commit()
    funcsdb = session.query(Call).all()
    assert len(funcsdb) == 0
    filedb = session.query(File).get(1)
    src_filedb = session.query(SourceFile).get(1)
    assert filedb.name == 'file'
    assert src_filedb.ext == 'src'

    session.close()
    db.drop_all()
Пример #17
0
def test_add_operation():
	db_url = 'postgresql://*****:*****@localhost:5432/src_file_one_to_one'	
	db = SQLAlchemyORM(db_url)
	db.create_all(True)

	filepath = 'some/path/file.src'
	file = File(filepath)
	src_file = SourceFile(file)

	f1 = Operation('get', src_file)
	src_file.add_code_element(f1)

	session = db.create_session()
	session.add(src_file)
	session.commit()	

	f1db = session.query(Operation).get(1)
	assert f1db.name == 'get'
	assert f1db.source_file_id == 1

	session.close()
	db.drop_all()	 
Пример #18
0
def test_one_to_one_relation():
	db_url = 'postgresql://*****:*****@localhost:5432/src_file_one_to_one'	
	db = SQLAlchemyORM(db_url)
	db.create_all(True)
	
	filepath = 'some/path/file.src'
	file = File(filepath)
	src_file1 = SourceFile(file)
	# src_file2 = SourceFile(file) #TODO(#42): how to test one-to-one relationship
	
	session = db.create_session()
	session.add(src_file1)
	# session.add(src_file2)
	session.commit()
	
	# src_filedb1 = session.query(SourceFile).get(1)
	# src_filedb2 = session.query(SourceFile).get(2)
	assert src_file1.file_id == 1
	# assert src_file2.file_id == 1 #TODO: one to one seems not working
	
	session.close()
	db.drop_all()
Пример #19
0
def test_get_commit_source_file():
    db_url = 'postgresql://*****:*****@localhost:5432/miner_sources'
    db = SQLAlchemyORM(db_url)
    db.create_all(True)
    repo = Repository('repo/terrame')
    sys = System('terrame', repo)
    miner = RepositoryMiner(repo, sys)
    commit_info = miner.get_commit_info(
        '082dff5e822ea1b4491911b7bf434a7f47a4be26')
    author = Author(Person(commit_info.author_name, commit_info.author_email))
    commit = Commit(commit_info, author, repo)
    session = db.create_session()
    for mod_info in commit_info.modifications:
        file = File(mod_info.new_path)
        sys.add_file(file)
        mod = Modification(mod_info, file, commit)
        if miner.is_source_file(file):
            srcfile = SourceFile(file)
            code_elements = miner.extract_code_elements(srcfile, mod)
            for element in code_elements:
                element.modification = mod
                session.add(element)
            session.add(mod)

    session.commit()
    afile = sys.get_file('base/lua/CellularSpace.lua')
    srcfiledb = session.query(SourceFile).filter_by(file_id=afile.id).first()
    assert srcfiledb.ext == 'lua'
    assert srcfiledb.name == 'CellularSpace'
    assert srcfiledb.code_elements_len() == 78

    functions = session.query(Operation).filter_by(
        source_file_id=srcfiledb.id).all()
    assert srcfiledb.code_element_exists(functions[0])
    assert functions[0].name == 'CellularSpace'

    session.close()
    db.drop_all()
Пример #20
0
def test_get_commit():
    db_url = 'postgresql://*****:*****@localhost:5432/miner_get_commit'
    db = SQLAlchemyORM(db_url)
    db.create_all(True)
    repo = Repository('repo/terrame')
    sys = System('terrame', repo)
    miner = RepositoryMiner(repo, sys)
    commit_info = miner.get_commit_info(
        '80a562be869dbb984229f608ae9a04d05c5e1689')

    assert commit_info.msg == 'Initial commit'
    assert commit_info.date.strftime(
        '%Y-%m-%d %H:%M:%S') == '2014-09-15 08:12:11'
    assert commit_info.hash == '80a562be869dbb984229f608ae9a04d05c5e1689'
    assert commit_info.author_name == 'pedro-andrade-inpe'
    assert commit_info.author_email == '*****@*****.**'
    assert len(commit_info.modifications) == 1
    assert commit_info.modifications[0].filename == 'LICENSE'
    assert commit_info.modifications[0].old_path is None
    assert commit_info.modifications[0].new_path == 'LICENSE'
    assert commit_info.modifications[0].added == 674
    assert commit_info.modifications[0].removed == 0
    assert commit_info.modifications[0].status == 'ADD'

    author = Author(Person(commit_info.author_name, commit_info.author_email))
    commit = Commit(commit_info, author, repo)
    fmodinfo = commit_info.modifications[0]
    file = File(fmodinfo.filename)
    filemod = Modification(fmodinfo, file, commit)
    session = db.create_session()
    session.add(repo)
    session.add(sys)
    session.add(commit)
    session.add(file)
    session.add(filemod)
    session.commit()

    filemoddb = session.query(Modification).get(1)
    commitdb = filemoddb.commit
    filedb = filemoddb.file

    assert commitdb.msg == 'Initial commit'
    assert commitdb.date.strftime('%Y-%m-%d %H:%M:%S') == '2014-09-15 08:12:11'
    assert commitdb.hash == '80a562be869dbb984229f608ae9a04d05c5e1689'
    assert commitdb.repository.path == repo.path
    assert commitdb.author.name == 'pedro-andrade-inpe'
    assert commitdb.author.email == '*****@*****.**'
    assert filedb.fullpath == 'LICENSE'
    assert filemoddb.old_path is None
    assert filemoddb.new_path == 'LICENSE'
    assert filemoddb.added == 674
    assert filemoddb.removed == 0
    assert filemoddb.status == 'ADD'

    commit_info = miner.get_commit_info(
        'ffb8347b2de44eb05f6c5eba3b3cb8b7716acebb')

    assert commit_info.msg == 'Delete LICENSE'
    assert commit_info.date.strftime(
        '%Y-%m-%d %H:%M:%S') == '2014-09-17 11:49:45'
    assert commit_info.hash == 'ffb8347b2de44eb05f6c5eba3b3cb8b7716acebb'
    assert commit_info.author_name == 'pedro-andrade-inpe'
    assert commit_info.author_email == '*****@*****.**'
    assert len(commit_info.modifications) == 1
    assert commit_info.modifications[0].filename == 'LICENSE'
    assert commit_info.modifications[0].old_path == 'LICENSE'
    assert commit_info.modifications[0].new_path is None
    assert commit_info.modifications[0].added == 0
    assert commit_info.modifications[0].removed == 674
    assert commit_info.modifications[0].status == 'DELETE'

    commit = Commit(commit_info, author, repo)
    fmodinfo = commit_info.modifications[0]
    filemod = Modification(fmodinfo, file, commit)
    session.add(commit)
    session.add(filemod)
    session.commit()

    filemoddb2 = session.query(Modification).get(2)
    commitdb2 = filemoddb2.commit
    filedb2 = filemoddb2.file

    assert commitdb2.msg == 'Delete LICENSE'
    assert commitdb2.date.strftime(
        '%Y-%m-%d %H:%M:%S') == '2014-09-17 11:49:45'
    assert commitdb2.hash == 'ffb8347b2de44eb05f6c5eba3b3cb8b7716acebb'
    assert commitdb2.repository.id == repo.id
    assert commitdb2.author.name == 'pedro-andrade-inpe'
    assert commitdb2.author.email == '*****@*****.**'
    assert filedb2.fullpath == 'LICENSE'
    assert filemoddb2.old_path == 'LICENSE'
    assert filemoddb2.new_path is None
    assert filemoddb2.added == 0
    assert filemoddb2.removed == 674
    assert filemoddb2.status == 'DELETE'

    filemoddb1 = session.query(Modification).get(1)
    commitdb1 = filemoddb1.commit
    filedb1 = filemoddb1.file

    assert commitdb1.msg == 'Initial commit'
    assert commitdb1.date.strftime(
        '%Y-%m-%d %H:%M:%S') == '2014-09-15 08:12:11'
    assert commitdb1.hash == '80a562be869dbb984229f608ae9a04d05c5e1689'
    assert commitdb1.repository.path == repo.path
    assert commitdb2.author.name == 'pedro-andrade-inpe'
    assert commitdb2.author.email == '*****@*****.**'
    assert filedb1.fullpath == 'LICENSE'
    assert filemoddb1.old_path is None
    assert filemoddb1.new_path == 'LICENSE'
    assert filemoddb1.added == 674
    assert filemoddb1.removed == 0
    assert filemoddb1.status == 'ADD'

    session.close()
    db.drop_all()
Пример #21
0
def test_add_relationship(mocker):
    db_url = 'postgresql://*****:*****@localhost:5432/eco_add_relation'
    db = SQLAlchemyORM(db_url)
    db.create_all(True)

    repo1 = Repository('repo/terrame')
    sys1 = System('terrame', repo1)
    f1 = File('some/path/file1.src')
    src1 = SourceFile(f1)
    f11 = Operation('get', src1)
    f12 = Operation('add', src1)
    c11 = Call('call', src1)
    src1.add_code_element(f11)
    src1.add_code_element(f12)
    src1.add_code_element(c11)
    sys1.add_source_file(src1)

    repo2 = Repository('repo/ca')
    sys2 = System('ca', repo2)
    f2 = File('some/path/file2.src')
    src2 = SourceFile(f2)
    f21 = Operation('call', src2)
    c21 = Call('get', src2)
    src2.add_code_element(f21)
    sys2.add_source_file(src2)

    session = db.create_session()
    session.add(src1)
    session.add(src2)
    session.commit()

    tme_author = Author(Person('TerraMe Dev', '*****@*****.**'))
    ca_author = Author(Person('CA Dev', '*****@*****.**'))
    mocker.patch.object(f11, 'author', return_value=tme_author, autospec=True)
    mocker.patch.object(f12, 'author', return_value=tme_author, autospec=True)
    mocker.patch.object(c11, 'author', return_value=tme_author, autospec=True)
    mocker.patch.object(f21, 'author', return_value=ca_author, autospec=True)
    mocker.patch.object(c21, 'author', return_value=ca_author, autospec=True)

    to_info = RelationInfo(sys1, src1, c11)
    from_info = FromRelationInfo(sys2, src2, f21, 10)
    rel1 = Relationship(from_info, to_info)

    to_info = RelationInfo(sys1, src1, f11)
    from_info = FromRelationInfo(sys2, src2, c21, 20)
    rel2 = Relationship(from_info, to_info)

    eco = Ecosystem()
    eco.add_relationship(rel1)
    eco.add_relationship(rel2)

    session.add(eco)
    session.commit()
    ecodb = session.query(Ecosystem).one()
    relsdb = ecodb.relationships

    assert len(relsdb) == 2

    rel1db = relsdb[0]
    assert rel1db.from_system.name == 'ca'
    assert rel1db.to_system.name == 'terrame'
    assert rel1db.from_source_file.name == 'file2'
    assert rel1db.to_source_file.name == 'file1'
    assert rel1db.from_code_element.name == 'call'
    assert rel1db.to_code_element.name == 'call'
    assert rel1db.from_author.name == 'CA Dev'
    assert rel1db.to_author.name == 'TerraMe Dev'
    assert rel1db.from_code_element_count == 10

    rel2db = relsdb[1]
    assert rel2db.from_system.name == 'ca'
    assert rel2db.to_system.name == 'terrame'
    assert rel2db.from_source_file.name == 'file2'
    assert rel2db.to_source_file.name == 'file1'
    assert rel2db.from_code_element.name == 'get'
    assert rel2db.to_code_element.name == 'get'
    assert rel2db.from_author.name == 'CA Dev'
    assert rel2db.to_author.name == 'TerraMe Dev'
    assert rel2db.from_code_element_count == 20

    session.close()
    db.drop_all()
Пример #22
0
 def _add_file(self, fullpath):
     file = File(fullpath)
     self.system.add_file(file)
     return file
Пример #23
0
def test_make_relations(mocker):
	mocker.patch.object(GitPython, 'IsGitRepo', return_value=True)
	mocker.patch.object(GitPython, 'CurrentBranch', return_value='master')
	repo1 = Repository('some/path/terrame')
	sys1 = System('terrame', repo1)
	f1 = File('Cell.lua')
	src1 = SourceFile(f1)
	op1 = Operation('Cell', src1)
	src1.add_code_element(op1)

	f2 = File('CellularSpace.lua')	
	src2 = SourceFile(f2)
	op2 = Operation('CellularSpace', src2)
	src2.add_code_element(op2)	

	sys1.add_source_file(src1)
	sys1.add_source_file(src2)

	repo2 = Repository('some/path/ca')
	sys2 = System('ca', repo2)
	f3 = File('Anneal.lua')
	src3 = SourceFile(f3)
	c1 = Call('Cell', src3)
	src3.add_code_element(c1)
	c2 = Call('CellularSpace', src3)
	src3.add_code_element(c2)

	sys2.add_source_file(src3)	

	ecosystem = Ecosystem()

	tme_author = Author(Person('TerraMe Dev', '*****@*****.**'))
	ca_author = Author(Person('CA Dev', '*****@*****.**'))
	mocker.patch.object(op1, 'author', return_value=tme_author, autospec=True)
	mocker.patch.object(op2, 'author', return_value=tme_author, autospec=True)
	mocker.patch.object(c1, 'author', return_value=ca_author, autospec=True)
	mocker.patch.object(c2, 'author', return_value=ca_author, autospec=True)	

	mocker.patch.object(EcosystemAnalyzer, '_total_of_calls', return_value=10)

	ecolyzer = EcosystemAnalyzer(ecosystem)
	ecolyzer.make_relations(sys2, sys1)

	relationships = ecosystem.relationships

	assert len(relationships) == 2

	rel1 = relationships[0]
	rel2 = relationships[1]

	assert rel1.from_system.name == 'ca'
	assert rel1.from_author.name == 'CA Dev'
	assert rel1.from_author.email == '*****@*****.**'
	assert rel1.to_system.name == 'terrame'
	assert rel1.to_author.name == 'TerraMe Dev'	
	assert rel1.to_author.email == '*****@*****.**'	
	assert rel1.from_code_element.name == rel1.to_code_element.name == 'Cell'
	
	assert rel2.from_system.name == 'ca'
	assert rel2.from_author.name == 'CA Dev'
	assert rel2.from_author.email == '*****@*****.**'	
	assert rel2.to_system.name == 'terrame'
	assert rel2.to_author.name == 'TerraMe Dev'	
	assert rel2.to_author.email == '*****@*****.**'	
	assert rel2.from_code_element.name == rel2.to_code_element.name == 'CellularSpace'	
Пример #24
0
def test_lua_reverse_engineering():
    operations = {
        'CellularSpace': True,
        'createNeighborhood': True,
        'add': True,
        'getCell': True,
        'get': True,
        'getCells': True,
        'getCellByID': True,
        'load': True,
        'loadShape': True,
        'loadNeighborhood': True,
        'notify': True,
        'sample': True,
        'save': True,
        'saveShape': True,
        'size': True,
        'split': True,
        'synchronize': True,
        'moore': True,
        'mxn': True,
        'vonneumann': True,
        'coord': True,
        '__len': True
    }

    calls = {
        'addNeighborhood': True,
        'addCell': True,
        'getNeighborhood': True,
        'caseof': True,
        'clear': True,
        'endswith': True,
        'getTime': True,
        'integer': True,
        'getDBName': True,
        'sub': True,
        'setDBType': True,
        'setDBName': True,
        'len': True,
        'setPort': True,
        'setHostName': True,
        'setUser': True,
        'setPassword': True,
        'setTheme': True,
        'setLayer': True,
        'setWhereClause': True,
        'clearAttrName': True,
        'addAttrName': True,
        'setReference': True,
        'getLayerName': True,
        'init': True,
        'forEachCell': True,
        'Neighborhood': True,
        'ipairs': True,
        'weightF': True,
        'filterF': True,
        'customWarningMsg': True,
        'namedParametersErrorMsg': True,
        'type': True,
        'defaultValueWarningMsg': True,
        'incompatibleTypesErrorMsg': True,
        'checkUnnecessaryParameters': True,
        'mandatoryArgumentErrorMsg': True,
        'incompatibleValuesErrorMsg': True,
        'switch': True,
        'deprecatedFunctionWarningMsg': True,
        'Coord': True,
        'readCSV': True,
        'tostring': True,
        'Cell': True,
        'customErrorMsg': True,
        'pairs': True,
        'tableParameterErrorMsg': True,
        'resourceNotFoundErrorMsg': True,
        'print': True,
        'argument': True,
        'Trajectory': True,
        'getn': True,
        'TeCellularSpace': True,
        'incompatibleFileExtensionErrorMsg': True,
        'setmetatable': True,
        'forEachElement': True
    }

    luafile = os.path.join(os.path.dirname(__file__), '../data',
                           'CellularSpace1.lua')
    file = File(luafile)
    src_file = SourceFile(file)
    src = open(luafile).read()
    analyzer = StaticAnalyzer()
    code_elements = analyzer.reverse_engineering(src_file, src)

    code_elements_dict = {}
    for element in code_elements:
        code_elements_dict[element.name] = True

    for k in operations.keys():
        assert code_elements_dict[k]

    for k in calls.keys():
        assert code_elements_dict[k]

    assert len(code_elements) == len(operations) + len(calls)

    for element in code_elements:
        if element.type == 'call':
            assert calls[element.name]
            assert element.name not in operations
        else:
            assert operations[element.name]
            assert element.name not in calls
Пример #25
0
def test_without_ext():
    file1 = File('some/path/noextfile')
    assert file1.fullpath == 'some/path/noextfile'

    file2 = File('noextfile')
    assert file2.fullpath == 'noextfile'
Пример #26
0
def test_source_code():
	filepath = 'repo/terrame/packages/base/lua/Cell.lua'
	file = File(filepath)
	src_file = SourceFile(file)
	assert src_file.source_code is not None	
Пример #27
0
def test_all_code_elements():
    src = """
package org.jfree.chart;

import java.awt.AlphaComposite;
import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Composite;
import java.awt.Font;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.Paint;
import java.awt.RenderingHints;
import java.awt.Shape;
import java.awt.Stroke;
import java.awt.geom.AffineTransform;
import java.awt.geom.Point2D;
import java.awt.geom.Rectangle2D;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import javax.swing.UIManager;
import javax.swing.event.EventListenerList;

import org.jfree.chart.block.BlockParams;
import org.jfree.chart.block.EntityBlockResult;
import org.jfree.chart.block.LengthConstraintType;
import org.jfree.chart.block.RectangleConstraint;
import org.jfree.chart.entity.EntityCollection;
import org.jfree.chart.entity.JFreeChartEntity;
import org.jfree.chart.event.ChartChangeEvent;
import org.jfree.chart.event.ChartChangeListener;
import org.jfree.chart.event.ChartProgressEvent;
import org.jfree.chart.event.ChartProgressEventType;
import org.jfree.chart.event.ChartProgressListener;
import org.jfree.chart.event.PlotChangeEvent;
import org.jfree.chart.event.PlotChangeListener;
import org.jfree.chart.event.TitleChangeEvent;
import org.jfree.chart.event.TitleChangeListener;
import org.jfree.chart.plot.CategoryPlot;
import org.jfree.chart.plot.Plot;
import org.jfree.chart.plot.PlotRenderingInfo;
import org.jfree.chart.plot.XYPlot;
import org.jfree.chart.title.LegendTitle;
import org.jfree.chart.title.TextTitle;
import org.jfree.chart.title.Title;
import org.jfree.chart.ui.Align;
import org.jfree.chart.ui.Drawable;
import org.jfree.chart.ui.HorizontalAlignment;
import org.jfree.chart.ui.RectangleEdge;
import org.jfree.chart.ui.RectangleInsets;
import org.jfree.chart.ui.Size2D;
import org.jfree.chart.ui.VerticalAlignment;
import org.jfree.chart.util.ObjectUtils;
import org.jfree.chart.util.PaintUtils;
import org.jfree.chart.util.SerialUtils;
import org.jfree.data.Range;

public class JFreeChart implements Drawable, TitleChangeListener,
        PlotChangeListener, Serializable, Cloneable {	

    private static final long serialVersionUID = -3470703747817429120L;		
    public static final Font DEFAULT_TITLE_FONT
            = new Font("SansSerif", Font.BOLD, 18);	
    public static final Paint DEFAULT_BACKGROUND_PAINT
            = UIManager.getColor("Panel.background");
	public static final Image DEFAULT_BACKGROUND_IMAGE = null;
	public static final int DEFAULT_BACKGROUND_IMAGE_ALIGNMENT = Align.FIT;		
	public static final float DEFAULT_BACKGROUND_IMAGE_ALPHA = 0.5f;  

    public static final RenderingHints.Key KEY_SUPPRESS_SHADOW_GENERATION
            = new RenderingHints.Key(0) {
        @Override
        public boolean isCompatibleValue(Object val) {
            return val instanceof Boolean; // <<< TODO: does consider it?
        }
    };		

    private transient RenderingHints renderingHints;	
    private String id;  
    private boolean borderVisible;
    private transient Stroke borderStroke;
    private transient Paint borderPaint;
    private RectangleInsets padding;	
    private TextTitle title;	 
    private List<Title> subtitles; 
    private Plot plot;    
		private transient Paint backgroundPaint;
	private transient Image backgroundImage;  // todo: not serialized yet	
	private int backgroundImageAlignment = Align.FIT;
    private float backgroundImageAlpha = 0.5f;
    private transient EventListenerList changeListeners;
    private transient EventListenerList progressListeners;
    private boolean notify; 
    private boolean elementHinting;	

    public JFreeChart(Plot plot) {
        this(null, null, plot, true);
    }	

    public JFreeChart(String title, Plot plot) {
        this(title, JFreeChart.DEFAULT_TITLE_FONT, plot, true);
    }	

    public JFreeChart(String title, Font titleFont, Plot plot,
                      boolean createLegend) {

        Objects.requireNonNull(plot, "plot");	
        this.id = null;
        plot.setChart(this);
        this.progressListeners = new EventListenerList();
        this.changeListeners = new EventListenerList();
        this.notify = true;  	
        this.renderingHints = new RenderingHints(
                RenderingHints.KEY_ANTIALIASING,
                RenderingHints.VALUE_ANTIALIAS_ON);		
        this.renderingHints.put(RenderingHints.KEY_STROKE_CONTROL,
                RenderingHints.VALUE_STROKE_PURE);	
        this.borderVisible = false;
        this.borderStroke = new BasicStroke(1.0f);
        this.borderPaint = Color.BLACK;	
		this.padding = RectangleInsets.ZERO_INSETS;
		this.plot = plot;
		plot.addChangeListener(this);	
		this.subtitles = new ArrayList<>();	  
        if (createLegend) {
            LegendTitle legend = new LegendTitle(this.plot);
            legend.setMargin(new RectangleInsets(1.0, 1.0, 1.0, 1.0));
            legend.setBackgroundPaint(Color.WHITE);
            legend.setPosition(RectangleEdge.BOTTOM);
            this.subtitles.add(legend);
            legend.addChangeListener(this);
        }    
        if (title != null) {
            if (titleFont == null) {
                titleFont = DEFAULT_TITLE_FONT;
            }
            this.title = new TextTitle(title, titleFont);
            this.title.addChangeListener(this);
        }
        this.backgroundPaint = DEFAULT_BACKGROUND_PAINT;
        this.backgroundImage = DEFAULT_BACKGROUND_IMAGE;
        this.backgroundImageAlignment = DEFAULT_BACKGROUND_IMAGE_ALIGNMENT;
        this.backgroundImageAlpha = DEFAULT_BACKGROUND_IMAGE_ALPHA;		        		            		      	                	                                
    }	   

    public String getID() {
        return this.id;
    }

    public void setID(String id) {
        this.id = id;
    }	

    public boolean getElementHinting() {
        return this.elementHinting;
    }		

    public void setElementHinting(boolean hinting) {
        this.elementHinting = hinting;
    }

    public RenderingHints getRenderingHints() {
        return this.renderingHints;
    }	

    public void setRenderingHints(RenderingHints renderingHints) {
        Objects.requireNonNull(renderingHints, "renderingHints");
        this.renderingHints = renderingHints;
        fireChartChanged();
    }

    public boolean isBorderVisible() {
        return this.borderVisible;
    }     	

    public void setBorderVisible(boolean visible) {
        this.borderVisible = visible;
        fireChartChanged();
    }    

    public Stroke getBorderStroke() {
        return this.borderStroke;
    }     

    public void setBorderStroke(Stroke stroke) {
        this.borderStroke = stroke;
        fireChartChanged();
    }     

    public Paint getBorderPaint() {
        return this.borderPaint;
    }

    public void setBorderPaint(Paint paint) {
        this.borderPaint = paint;
        fireChartChanged();
    }   

    public RectangleInsets getPadding() {
        return this.padding;
    }

    public void setPadding(RectangleInsets padding) {
        Objects.requireNonNull(padding, "padding");
        this.padding = padding;
        notifyListeners(new ChartChangeEvent(this));
    }  

    public TextTitle getTitle() {
        return this.title;
    }

    public void setTitle(TextTitle title) {
        if (this.title != null) {
            this.title.removeChangeListener(this);
        }
        this.title = title;
        if (title != null) {
            title.addChangeListener(this);
        }
        fireChartChanged();
    }  

    public void addLegend(LegendTitle legend) {
        addSubtitle(legend);
    }  

    public LegendTitle getLegend() {
        return getLegend(0);
    } 

    public LegendTitle getLegend(int index) {
        int seen = 0;
        for (Title subtitle : this.subtitles) {
            if (subtitle instanceof LegendTitle) {
                if (seen == index) {
                    return (LegendTitle) subtitle;
                }
                else {
                    seen++;
                }
            }
        }
        return null;
    } 

    public void removeLegend() {
        removeSubtitle(getLegend());
    }   

    public List<Title> getSubtitles() {
        return new ArrayList<>(this.subtitles);
    }    

    public void setSubtitles(List<Title> subtitles) {
        Objects.requireNonNull(subtitles, "subtitles");
        setNotify(false);
        clearSubtitles();
        for (Title t: subtitles) {
            if (t != null) {
                addSubtitle(t);
            }
        }
        setNotify(true);  // this fires a ChartChangeEvent
    }

    public int getSubtitleCount() {
        return this.subtitles.size();
    }      

    public Title getSubtitle(int index) {
        if ((index < 0) || (index >= getSubtitleCount())) {
            throw new IllegalArgumentException("Index out of range.");
        }
        return this.subtitles.get(index);
    }      

    public void addSubtitle(Title subtitle) {
        Objects.requireNonNull(subtitle, "subtitle");
        this.subtitles.add(subtitle);
        subtitle.addChangeListener(this);
        fireChartChanged();
    }   

    public void addSubtitle(int index, Title subtitle) {
        if (index < 0 || index > getSubtitleCount()) {
            throw new IllegalArgumentException(
                    "The 'index' argument is out of range.");
        }
        Objects.requireNonNull(subtitle, "subtitle");
        this.subtitles.add(index, subtitle);
        subtitle.addChangeListener(this);
        fireChartChanged();
    }       

    public void clearSubtitles() {
        for (Title t : this.subtitles) {
            t.removeChangeListener(this);
        }
        this.subtitles.clear();
        fireChartChanged();
    } 

    public void removeSubtitle(Title title) {
        this.subtitles.remove(title);
        fireChartChanged();
    }    

    public Plot getPlot() {
        return this.plot;
    }  

    public boolean getAntiAlias() {
        Object val = this.renderingHints.get(RenderingHints.KEY_ANTIALIASING);
        return RenderingHints.VALUE_ANTIALIAS_ON.equals(val);
    }         

    public void setAntiAlias(boolean flag) {
        Object hint = flag ? RenderingHints.VALUE_ANTIALIAS_ON 
                : RenderingHints.VALUE_ANTIALIAS_OFF;
        this.renderingHints.put(RenderingHints.KEY_ANTIALIASING, hint);
        fireChartChanged();
    }  

    public Object getTextAntiAlias() {
        return this.renderingHints.get(RenderingHints.KEY_TEXT_ANTIALIASING);
    }   

    public void setTextAntiAlias(boolean flag) {
        if (flag) {
            setTextAntiAlias(RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
        }
        else {
            setTextAntiAlias(RenderingHints.VALUE_TEXT_ANTIALIAS_OFF);
        }
    } 

    public void setTextAntiAlias(Object val) {
        this.renderingHints.put(RenderingHints.KEY_TEXT_ANTIALIASING, val);
        notifyListeners(new ChartChangeEvent(this));
    }   

    public Paint getBackgroundPaint() {
        return this.backgroundPaint;
    }      

    public void setBackgroundPaint(Paint paint) {

        if (this.backgroundPaint != null) {
            if (!this.backgroundPaint.equals(paint)) {
                this.backgroundPaint = paint;
                fireChartChanged();
            }
        }
        else {
            if (paint != null) {
                this.backgroundPaint = paint;
                fireChartChanged();
            }
        }
    }  

    public Image getBackgroundImage() {
        return this.backgroundImage;
    }

    public void setBackgroundImage(Image image) {

        if (this.backgroundImage != null) {
            if (!this.backgroundImage.equals(image)) {
                this.backgroundImage = image;
                fireChartChanged();
            }
        }
        else {
            if (image != null) {
                this.backgroundImage = image;
                fireChartChanged();
            }
        }
    }

    public int getBackgroundImageAlignment() {
        return this.backgroundImageAlignment;
    }

    public void setBackgroundImageAlignment(int alignment) {
        if (this.backgroundImageAlignment != alignment) {
            this.backgroundImageAlignment = alignment;
            fireChartChanged();
        }
    }   

    public float getBackgroundImageAlpha() {
        return this.backgroundImageAlpha;
    }

    public void setBackgroundImageAlpha(float alpha) {
        if (this.backgroundImageAlpha != alpha) {
            this.backgroundImageAlpha = alpha;
            fireChartChanged();
        }
    }      

    public boolean isNotify() {
        return this.notify;
    }

    public void setNotify(boolean notify) {
        this.notify = notify;
        if (notify) {
            notifyListeners(new ChartChangeEvent(this));
        }
    }    

    public void draw(Graphics2D g2, Rectangle2D area) {
        draw(g2, area, null, null);
    }

    public void draw(Graphics2D g2, Rectangle2D area, ChartRenderingInfo info) {
        draw(g2, area, null, info);
    }       

    public void draw(Graphics2D g2, Rectangle2D chartArea, Point2D anchor,
             ChartRenderingInfo info) {

        notifyListeners(new ChartProgressEvent(this, this,
                ChartProgressEventType.DRAWING_STARTED, 0));
        
        if (this.elementHinting) {
            Map<String, String> m = new HashMap<>();
            if (this.id != null) {
                m.put("id", this.id);
            }
            m.put("ref", "JFREECHART_TOP_LEVEL");            
            g2.setRenderingHint(ChartHints.KEY_BEGIN_ELEMENT, m);            
        }

        EntityCollection entities = null;
        if (info != null) {
            info.clear();
            info.setChartArea(chartArea);
            entities = info.getEntityCollection();
        }
        if (entities != null) {
            entities.add(new JFreeChartEntity((Rectangle2D) chartArea.clone(),
                    this));
        }   

       Shape savedClip = g2.getClip();
        g2.clip(chartArea);

        g2.addRenderingHints(this.renderingHints);

        if (this.backgroundPaint != null) {
            g2.setPaint(this.backgroundPaint);
            g2.fill(chartArea);
        }

        if (this.backgroundImage != null) {
            Composite originalComposite = g2.getComposite();
            g2.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER,
                    this.backgroundImageAlpha));
            Rectangle2D dest = new Rectangle2D.Double(0.0, 0.0,
                    this.backgroundImage.getWidth(null),
                    this.backgroundImage.getHeight(null));
            Align.align(dest, chartArea, this.backgroundImageAlignment);
            g2.drawImage(this.backgroundImage, (int) dest.getX(),
                    (int) dest.getY(), (int) dest.getWidth(),
                    (int) dest.getHeight(), null);
            g2.setComposite(originalComposite);
        }     

        if (isBorderVisible()) {
            Paint paint = getBorderPaint();
            Stroke stroke = getBorderStroke();
            if (paint != null && stroke != null) {
                Rectangle2D borderArea = new Rectangle2D.Double(
                        chartArea.getX(), chartArea.getY(),
                        chartArea.getWidth() - 1.0, chartArea.getHeight()
                        - 1.0);
                g2.setPaint(paint);
                g2.setStroke(stroke);
                g2.draw(borderArea);
            }
        } 

        Rectangle2D nonTitleArea = new Rectangle2D.Double();
        nonTitleArea.setRect(chartArea);
        this.padding.trim(nonTitleArea);

        if (this.title != null && this.title.isVisible()) {
            EntityCollection e = drawTitle(this.title, g2, nonTitleArea,
                    (entities != null));
            if (e != null && entities != null) {
                entities.addAll(e);
            }
        }    

        for (Title currentTitle : this.subtitles) {
            if (currentTitle.isVisible()) {
                EntityCollection e = drawTitle(currentTitle, g2, nonTitleArea,
                        (entities != null));
                if (e != null && entities != null) {
                    entities.addAll(e);
                }
            }
        }  

        Rectangle2D plotArea = nonTitleArea;

        PlotRenderingInfo plotInfo = null;
        if (info != null) {
            plotInfo = info.getPlotInfo();
        }
        this.plot.draw(g2, plotArea, anchor, null, plotInfo);
        g2.setClip(savedClip);
        if (this.elementHinting) {         
            g2.setRenderingHint(ChartHints.KEY_END_ELEMENT, Boolean.TRUE);            
        }

        notifyListeners(new ChartProgressEvent(this, this,
                ChartProgressEventType.DRAWING_FINISHED, 100));                                      
    }    

    private Rectangle2D createAlignedRectangle2D(Size2D dimensions,
            Rectangle2D frame, HorizontalAlignment hAlign,
            VerticalAlignment vAlign) {
        Objects.requireNonNull(hAlign, "hAlign");
        Objects.requireNonNull(vAlign, "vAlign");
        double x = Double.NaN;
        double y = Double.NaN;
        switch (hAlign) {
            case LEFT:
                x = frame.getX();
                break;
            case CENTER:
                x = frame.getCenterX() - (dimensions.width / 2.0);
                break;
            case RIGHT:
                x = frame.getMaxX() - dimensions.width;
                break;
            default:
                throw new IllegalStateException("Unexpected enum value " + hAlign);
        }
        switch (vAlign) {
            case TOP:
                y = frame.getY();
                break;
            case CENTER:
                y = frame.getCenterY() - (dimensions.height / 2.0);
                break;
            case BOTTOM:
                y = frame.getMaxY() - dimensions.height;
                break;
            default:
                throw new IllegalStateException("Unexpected enum value " + hAlign);
        }

        return new Rectangle2D.Double(x, y, dimensions.width,
                dimensions.height);
    }

    protected EntityCollection drawTitle(Title t, Graphics2D g2,
                                         Rectangle2D area, boolean entities) {

        Objects.requireNonNull(t, "t");
        Objects.requireNonNull(area, "area");
        Rectangle2D titleArea;
        RectangleEdge position = t.getPosition();
        double ww = area.getWidth();
        if (ww <= 0.0) {
            return null;
        }
        double hh = area.getHeight();
        if (hh <= 0.0) {
            return null;
        }
        RectangleConstraint constraint = new RectangleConstraint(ww,
                new Range(0.0, ww), LengthConstraintType.RANGE, hh,
                new Range(0.0, hh), LengthConstraintType.RANGE);
        Object retValue = null;
        BlockParams p = new BlockParams();
        p.setGenerateEntities(entities);
        if (position == RectangleEdge.TOP) {
            Size2D size = t.arrange(g2, constraint);
            titleArea = createAlignedRectangle2D(size, area,
                    t.getHorizontalAlignment(), VerticalAlignment.TOP);
            retValue = t.draw(g2, titleArea, p);
            area.setRect(area.getX(), Math.min(area.getY() + size.height,
                    area.getMaxY()), area.getWidth(), Math.max(area.getHeight()
                    - size.height, 0));
        } else if (position == RectangleEdge.BOTTOM) {
            Size2D size = t.arrange(g2, constraint);
            titleArea = createAlignedRectangle2D(size, area,
                    t.getHorizontalAlignment(), VerticalAlignment.BOTTOM);
            retValue = t.draw(g2, titleArea, p);
            area.setRect(area.getX(), area.getY(), area.getWidth(),
                    area.getHeight() - size.height);
        } else if (position == RectangleEdge.RIGHT) {
            Size2D size = t.arrange(g2, constraint);
            titleArea = createAlignedRectangle2D(size, area,
                    HorizontalAlignment.RIGHT, t.getVerticalAlignment());
            retValue = t.draw(g2, titleArea, p);
            area.setRect(area.getX(), area.getY(), area.getWidth()
                    - size.width, area.getHeight());
        } else if (position == RectangleEdge.LEFT) {
            Size2D size = t.arrange(g2, constraint);
            titleArea = createAlignedRectangle2D(size, area,
                    HorizontalAlignment.LEFT, t.getVerticalAlignment());
            retValue = t.draw(g2, titleArea, p);
            area.setRect(area.getX() + size.width, area.getY(), area.getWidth()
                    - size.width, area.getHeight());
        }
        else {
            throw new RuntimeException("Unrecognised title position.");
        }
        EntityCollection result = null;
        if (retValue instanceof EntityBlockResult) {
            EntityBlockResult ebr = (EntityBlockResult) retValue;
            result = ebr.getEntityCollection();
        }
        return result;
    }     

    public BufferedImage createBufferedImage(int width, int height) {
        return createBufferedImage(width, height, null);
    }    

    public BufferedImage createBufferedImage(int width, int height,
                                             ChartRenderingInfo info) {
        return createBufferedImage(width, height, BufferedImage.TYPE_INT_ARGB,
                info);
    } 

    public BufferedImage createBufferedImage(int width, int height,
            int imageType, ChartRenderingInfo info) {
        BufferedImage image = new BufferedImage(width, height, imageType);
        Graphics2D g2 = image.createGraphics();
        draw(g2, new Rectangle2D.Double(0, 0, width, height), null, info);
        g2.dispose();
        return image;
    }        

    public BufferedImage createBufferedImage(int imageWidth,
                                             int imageHeight,
                                             double drawWidth,
                                             double drawHeight,
                                             ChartRenderingInfo info) {

        BufferedImage image = new BufferedImage(imageWidth, imageHeight,
                BufferedImage.TYPE_INT_ARGB);
        Graphics2D g2 = image.createGraphics();
        double scaleX = imageWidth / drawWidth;
        double scaleY = imageHeight / drawHeight;
        AffineTransform st = AffineTransform.getScaleInstance(scaleX, scaleY);
        g2.transform(st);
        draw(g2, new Rectangle2D.Double(0, 0, drawWidth, drawHeight), null,
                info);
        g2.dispose();
        return image;
    }   

    public void handleClick(int x, int y, ChartRenderingInfo info) {
        this.plot.handleClick(x, y, info.getPlotInfo());
    }   

    public void addChangeListener(ChartChangeListener listener) {
        Objects.requireNonNull(listener, "listener");
        this.changeListeners.add(ChartChangeListener.class, listener);
    }    

    public void removeChangeListener(ChartChangeListener listener) {
        Objects.requireNonNull(listener, "listener");
        this.changeListeners.remove(ChartChangeListener.class, listener);
    }    

    public void fireChartChanged() {
        ChartChangeEvent event = new ChartChangeEvent(this);
        notifyListeners(event);
    }     

    protected void notifyListeners(ChartChangeEvent event) {
        if (this.notify) {
            Object[] listeners = this.changeListeners.getListenerList();
            for (int i = listeners.length - 2; i >= 0; i -= 2) {
                if (listeners[i] == ChartChangeListener.class) {
                    ((ChartChangeListener) listeners[i + 1]).chartChanged(
                            event);
                }
            }
        }
    }   

    public void addProgressListener(ChartProgressListener listener) {
        this.progressListeners.add(ChartProgressListener.class, listener);
    }

    public void removeProgressListener(ChartProgressListener listener) {
        this.progressListeners.remove(ChartProgressListener.class, listener);
    }         

    protected void notifyListeners(ChartProgressEvent event) {
        Object[] listeners = this.progressListeners.getListenerList();
        for (int i = listeners.length - 2; i >= 0; i -= 2) {
            if (listeners[i] == ChartProgressListener.class) {
                ((ChartProgressListener) listeners[i + 1]).chartProgress(event);
            }
        }
    }  

    @Override
    public void titleChanged(TitleChangeEvent event) {
        event.setChart(this);
        notifyListeners(event);
    }        

    @Override
    public void plotChanged(PlotChangeEvent event) {
        event.setChart(this);
        notifyListeners(event);
    }        

    @Override
    public boolean equals(Object obj) {
        if (obj == this) {
            return true;
        }
        if (!(obj instanceof JFreeChart)) {
            return false;
        }
        JFreeChart that = (JFreeChart) obj;
        if (!this.renderingHints.equals(that.renderingHints)) {
            return false;
        }
        if (this.borderVisible != that.borderVisible) {
            return false;
        }
        if (!ObjectUtils.equal(this.borderStroke, that.borderStroke)) {
            return false;
        }
        if (!PaintUtils.equal(this.borderPaint, that.borderPaint)) {
            return false;
        }
        if (!this.padding.equals(that.padding)) {
            return false;
        }
        if (!ObjectUtils.equal(this.title, that.title)) {
            return false;
        }
        if (!ObjectUtils.equal(this.subtitles, that.subtitles)) {
            return false;
        }
        if (!ObjectUtils.equal(this.plot, that.plot)) {
            return false;
        }
        if (!PaintUtils.equal(
            this.backgroundPaint, that.backgroundPaint
        )) {
            return false;
        }
        if (!ObjectUtils.equal(this.backgroundImage,
                that.backgroundImage)) {
            return false;
        }
        if (this.backgroundImageAlignment != that.backgroundImageAlignment) {
            return false;
        }
        if (this.backgroundImageAlpha != that.backgroundImageAlpha) {
            return false;
        }
        if (this.notify != that.notify) {
            return false;
        }
        return true;
    }  

    private void writeObject(ObjectOutputStream stream) throws IOException {
        stream.defaultWriteObject();
        SerialUtils.writeStroke(this.borderStroke, stream);
        SerialUtils.writePaint(this.borderPaint, stream);
        SerialUtils.writePaint(this.backgroundPaint, stream);
    }     

    private void readObject(ObjectInputStream stream)
        throws IOException, ClassNotFoundException {
        stream.defaultReadObject();
        this.borderStroke = SerialUtils.readStroke(stream);
        this.borderPaint = SerialUtils.readPaint(stream);
        this.backgroundPaint = SerialUtils.readPaint(stream);
        this.progressListeners = new EventListenerList();
        this.changeListeners = new EventListenerList();
        this.renderingHints = new RenderingHints(
                RenderingHints.KEY_ANTIALIASING,
                RenderingHints.VALUE_ANTIALIAS_ON);
        this.renderingHints.put(RenderingHints.KEY_STROKE_CONTROL,
                RenderingHints.VALUE_STROKE_PURE);
        
        if (this.title != null) {
            this.title.addChangeListener(this);
        }

        for (int i = 0; i < getSubtitleCount(); i++) {
            getSubtitle(i).addChangeListener(this);
        }
        this.plot.addChangeListener(this);
    }   

    @Override
    public Object clone() throws CloneNotSupportedException {
        JFreeChart chart = (JFreeChart) super.clone();

        chart.renderingHints = (RenderingHints) this.renderingHints.clone();

        if (this.title != null) {
            chart.title = (TextTitle) this.title.clone();
            chart.title.addChangeListener(chart);
        }

        chart.subtitles = new ArrayList<>();
        for (int i = 0; i < getSubtitleCount(); i++) {
            Title subtitle = (Title) getSubtitle(i).clone();
            chart.subtitles.add(subtitle);
            subtitle.addChangeListener(chart);
        }

        if (this.plot != null) {
            chart.plot = (Plot) this.plot.clone();
            chart.plot.addChangeListener(chart);
        }

        chart.progressListeners = new EventListenerList();
        chart.changeListeners = new EventListenerList();
        return chart;
    }               		        	    		     	    	    	
}
    """

    file = File('JFreeChart.java')
    src_file = SourceFile(file)
    analyzer = StaticAnalyzer()
    code_elements = analyzer.reverse_engineering(src_file, src)

    calls = []
    operations = []
    for c in code_elements:
        if isinstance(c, Call):
            calls.append(c)
        elif isinstance(c, Operation):
            operations.append(c)

    parser_expected_calls = {
        'plot.Plot.clone': 1,
        'title.TextTitle.clone': 1,
        'renderingHints.RenderingHints.clone': 1,
        'super.Object.clone': 1,
        'throws.CloneNotSupportedException.CloneNotSupportedException': 1,
        'SerialUtils.SerialUtils.readPaint': 2,
        'SerialUtils.SerialUtils.readStroke': 1,
        'stream.ObjectInputStream.defaultReadObject': 1,
        'throws.ClassNotFoundException.ClassNotFoundException': 1,
        'SerialUtils.SerialUtils.writePaint': 2,
        'SerialUtils.SerialUtils.writeStroke': 1,
        'SerialUtils.SerialUtils.writeStroke': 1,
        'stream.ObjectOutputStream.defaultWriteObject': 1,
        'throws.IOException.IOException': 2,
        'padding.RectangleInsets.equals': 1,
        'PaintUtils.PaintUtils.equal': 2,
        'ObjectUtils.ObjectUtils.equal': 5,
        'renderingHints.RenderingHints.equals': 1,
        'event.PlotChangeEvent.setChart': 1,
        'event.TitleChangeEvent.setChart': 1,
        'progressListeners.EventListenerList.getListenerList': 1,
        'progressListeners.EventListenerList.remove': 1,
        'progressListeners.EventListenerList.add': 1,
        'listeners.Object.length': 2,
        'changeListeners.EventListenerList.getListenerList': 1,
        'changeListeners.EventListenerList.remove': 1,
        'changeListeners.EventListenerList.add': 1,
        'plot.Plot.handleClick': 1,
        'g2.Graphics2D.transform': 1,
        'AffineTransform.AffineTransform.getScaleInstance': 1,
        'g2.Graphics2D.dispose': 2,
        'image.BufferedImage.createGraphics': 2,
        'new.BufferedImage.BufferedImage': 2,
        'BufferedImage.BufferedImage.TYPE_INT_ARGB': 2,
        'ebr.EntityBlockResult.getEntityCollection': 1,
        'new.RuntimeException.RuntimeException': 1,
        'HorizontalAlignment.HorizontalAlignment.LEFT': 1,
        'RectangleEdge.RectangleEdge.LEFT': 1,
        'size.Size2D.width': 3,
        't.Title.getVerticalAlignment': 2,
        'HorizontalAlignment.HorizontalAlignment.RIGHT': 1,
        'RectangleEdge.RectangleEdge.RIGHT': 1,
        'VerticalAlignment.VerticalAlignment.BOTTOM': 1,
        'Math.Math.max': 1,
        'area.Rectangle2D.getMaxY': 1,
        'size.Size2D.height': 3,
        'area.Rectangle2D.getY': 4,
        'Math.Math.min': 1,
        'area.Rectangle2D.getX': 4,
        'area.Rectangle2D.setRect': 4,
        't.Title.draw': 4,
        'VerticalAlignment.VerticalAlignment.TOP': 1,
        't.Title.getHorizontalAlignment': 2,
        't.Title.arrange': 4,
        'RectangleEdge.RectangleEdge.TOP': 1,
        'p.BlockParams.setGenerateEntities': 1,
        'new.BlockParams.BlockParams': 1,
        'LengthConstraintType.LengthConstraintType.RANGE': 2,
        'new.Range.Range': 2,
        'new.RectangleConstraint.RectangleConstraint': 1,
        'area.Rectangle2D.getHeight': 5,
        'area.Rectangle2D.getWidth': 5,
        't.Title.getPosition': 1,
        'frame.Rectangle2D.getMaxY': 1,
        'dimensions.Size2D.height': 3,
        'frame.Rectangle2D.getCenterY': 1,
        'frame.Rectangle2D.getY': 1,
        'new.IllegalStateException.IllegalStateException': 2,
        'frame.Rectangle2D.getMaxX': 1,
        'dimensions.Size2D.width': 3,
        'frame.Rectangle2D.getCenterX': 1,
        'frame.Rectangle2D.getX': 1,
        'Double.Double.NaN': 2,
        'ChartProgressEventType.ChartProgressEventType.DRAWING_FINISHED': 1,
        'Boolean.Boolean.TRUE': 1,
        'ChartHints.ChartHints.KEY_END_ELEMENT': 1,
        'g2.Graphics2D.setClip': 1,
        'plot.Plot.draw': 1,
        'info.ChartRenderingInfo.getPlotInfo': 2,
        'currentTitle.Title.isVisible': 1,
        'entities.EntityCollection.addAll': 2,
        'title.TextTitle.isVisible': 1,
        'padding.RectangleInsets.trim': 1,
        'nonTitleArea.Rectangle2D.setRect': 1,
        'g2.Graphics2D.draw': 1,
        'g2.Graphics2D.setStroke': 1,
        'chartArea.Rectangle2D.getHeight': 1,
        'chartArea.Rectangle2D.getWidth': 1,
        'chartArea.Rectangle2D.getY': 1,
        'chartArea.Rectangle2D.getX': 1,
        'Rectangle2D.Rectangle2D.Double': 6,
        'dest.Rectangle2D.getHeight': 1,
        'dest.Rectangle2D.getWidth': 1,
        'dest.Rectangle2D.getY': 1,
        'dest.Rectangle2D.getX': 1,
        'g2.Graphics2D.drawImage': 1,
        'Align.Align.align': 1,
        'backgroundImage.Image.getHeight': 1,
        'backgroundImage.Image.getWidth': 1,
        'new.Rectangle2D.Rectangle2D': 6,
        'AlphaComposite.AlphaComposite.SRC_OVER': 1,
        'AlphaComposite.AlphaComposite.getInstance': 1,
        'g2.Graphics2D.setComposite': 2,
        'g2.Graphics2D.getComposite': 1,
        'g2.Graphics2D.fill': 1,
        'g2.Graphics2D.setPaint': 2,
        'g2.Graphics2D.addRenderingHints': 1,
        'g2.Graphics2D.clip': 1,
        'g2.Graphics2D.getClip': 1,
        'chartArea.Rectangle2D.clone': 1,
        'new.JFreeChartEntity.JFreeChartEntity': 1,
        'entities.EntityCollection.add': 1,
        'info.ChartRenderingInfo.getEntityCollection': 1,
        'info.ChartRenderingInfo.setChartArea': 1,
        'info.ChartRenderingInfo.clear': 1,
        'ChartHints.ChartHints.KEY_BEGIN_ELEMENT': 1,
        'g2.Graphics2D.setRenderingHint': 2,
        'm.Map.put': 2,
        'new.HashMap.HashMap': 1,
        'ChartProgressEventType.ChartProgressEventType.DRAWING_STARTED': 1,
        'new.ChartProgressEvent.ChartProgressEvent': 2,
        'backgroundImage.Image.equals': 1,
        'backgroundPaint.Paint.equals': 1,
        'RenderingHints.RenderingHints.VALUE_TEXT_ANTIALIAS_OFF': 1,
        'RenderingHints.RenderingHints.VALUE_TEXT_ANTIALIAS_ON': 1,
        'RenderingHints.RenderingHints.KEY_TEXT_ANTIALIASING': 2,
        'RenderingHints.RenderingHints.VALUE_ANTIALIAS_OFF': 1,
        'renderingHints.RenderingHints.get': 2,
        'subtitles.List.remove': 1,
        'subtitles.List.clear': 1,
        't.Title.removeChangeListener': 1,
        'subtitle.Title.addChangeListener': 3,
        'subtitles.List.get': 1,
        'new.IllegalArgumentException.IllegalArgumentException': 2,
        'subtitles.List.size': 1,
        'title.TextTitle.removeChangeListener': 1,
        'new.ChartChangeEvent.ChartChangeEvent': 4,
        'title.TextTitle.addChangeListener': 4,
        'new.TextTitle.TextTitle': 1,
        'legend.LegendTitle.addChangeListener': 1,
        'subtitles.List.add': 4,
        'RectangleEdge.RectangleEdge.BOTTOM': 2,
        'legend.LegendTitle.setPosition': 1,
        'Color.Color.WHITE': 1,
        'legend.LegendTitle.setBackgroundPaint': 1,
        'new.RectangleInsets.RectangleInsets': 1,
        'legend.LegendTitle.setMargin': 1,
        'new.LegendTitle.LegendTitle': 1,
        'new.ArrayList.ArrayList': 3,
        'plot.Plot.addChangeListener': 3,
        'RectangleInsets.RectangleInsets.ZERO_INSETS': 1,
        'Color.Color.BLACK': 1,
        'new.BasicStroke.BasicStroke': 1,
        'RenderingHints.RenderingHints.VALUE_STROKE_PURE': 2,
        'RenderingHints.RenderingHints.KEY_STROKE_CONTROL': 2,
        'renderingHints.RenderingHints.put': 4,
        'RenderingHints.RenderingHints.VALUE_ANTIALIAS_ON': 4,
        'RenderingHints.RenderingHints.KEY_ANTIALIASING': 4,
        'new.EventListenerList.EventListenerList': 6,
        'plot.Plot.setChart': 1,
        'Objects.Objects.requireNonNull': 12,
        '@.Override.@': 5,
        'RenderingHints.RenderingHints.Key': 1,
        'new.RenderingHints.RenderingHints': 3,
        'Align.Align.FIT': 2,
        'UIManager.UIManager.getColor': 1,
        'Font.Font.BOLD': 1,
        'new.Font.Font': 1,
        'implements.implements.Cloneable': 1,
        'implements.implements.Serializable': 1,
        'implements.implements.PlotChangeListener': 1,
        'implements.implements.TitleChangeListener': 1,
        'implements.implements.Drawable': 1,
    }

    expected_calls = {}
    for c in parser_expected_calls:
        call_caller = c.split('.')
        if len(call_caller) > 2:
            key = f'{call_caller[1]}.{call_caller[2]}'
            expected_calls[key] = 1
        else:
            expected_calls[c] = 1

    parser_expected_operations = {
        'public.JFreeChart.clone': 1,
        'public.JFreeChart.equals': 1,
        'public.JFreeChart.plotChanged': 1,
        'public.JFreeChart.titleChanged': 1,
        'public.JFreeChart.removeProgressListener': 1,
        'public.JFreeChart.addProgressListener': 1,
        'protected.JFreeChart.notifyListeners': 2,
        'public.JFreeChart.fireChartChanged': 1,
        'public.JFreeChart.removeChangeListener': 1,
        'public.JFreeChart.addChangeListener': 1,
        'public.JFreeChart.handleClick': 1,
        'public.JFreeChart.createBufferedImage': 4,
        'protected.JFreeChart.drawTitle': 1,
        'public.JFreeChart.draw': 3,
        'public.JFreeChart.setNotify': 1,
        'public.JFreeChart.isNotify': 1,
        'public.JFreeChart.setBackgroundImageAlpha': 1,
        'public.JFreeChart.getBackgroundImageAlpha': 1,
        'public.JFreeChart.setBackgroundImageAlignment': 1,
        'public.JFreeChart.getBackgroundImageAlignment': 1,
        'public.JFreeChart.setBackgroundImage': 1,
        'public.JFreeChart.getBackgroundImage': 1,
        'public.JFreeChart.setBackgroundPaint': 1,
        'public.JFreeChart.getBackgroundPaint': 1,
        'public.JFreeChart.setTextAntiAlias': 2,
        'public.JFreeChart.getTextAntiAlias': 1,
        'public.JFreeChart.setAntiAlias': 1,
        'public.JFreeChart.getAntiAlias': 1,
        'public.JFreeChart.getPlot': 1,
        'public.JFreeChart.removeSubtitle': 1,
        'public.JFreeChart.clearSubtitles': 1,
        'public.JFreeChart.addSubtitle': 2,
        'public.JFreeChart.getSubtitle': 1,
        'public.JFreeChart.getSubtitleCount': 1,
        'public.JFreeChart.setSubtitles': 1,
        'public.JFreeChart.getSubtitles': 1,
        'public.JFreeChart.removeLegend': 1,
        'public.JFreeChart.getLegend': 2,
        'public.JFreeChart.addLegend': 1,
        'public.JFreeChart.setTitle': 1,
        'public.JFreeChart.getTitle': 1,
        'public.JFreeChart.setPadding': 1,
        'public.JFreeChart.getPadding': 1,
        'public.JFreeChart.setBorderPaint': 1,
        'public.JFreeChart.getBorderPaint': 1,
        'public.JFreeChart.setBorderStroke': 1,
        'public.JFreeChart.getBorderStroke': 1,
        'public.JFreeChart.setBorderVisible': 1,
        'public.JFreeChart.isBorderVisible': 1,
        'public.JFreeChart.setRenderingHints': 1,
        'public.JFreeChart.getRenderingHints': 1,
        'public.JFreeChart.setElementHinting': 1,
        'public.JFreeChart.getElementHinting': 1,
        'public.JFreeChart.setID': 1,
        'public.JFreeChart.getID': 1,
        'public.JFreeChart.isCompatibleValue': 1,
        'final.public.static.JFreeChart.KEY_SUPPRESS_SHADOW_GENERATION': 1,
        'final.public.static.JFreeChart.DEFAULT_BACKGROUND_IMAGE_ALPHA': 1,
        'final.public.static.JFreeChart.DEFAULT_BACKGROUND_IMAGE_ALIGNMENT': 1,
        'final.public.static.JFreeChart.DEFAULT_BACKGROUND_IMAGE': 1,
        'final.public.static.JFreeChart.DEFAULT_BACKGROUND_PAINT': 1,
        'final.public.static.JFreeChart.DEFAULT_TITLE_FONT': 1,
        'public.JFreeChart.JFreeChart': 3,
        'public.extends.JFreeChart': 1,
    }

    expected_operations = {}
    for c in parser_expected_operations:
        operation_modifiers = c.split('.')
        key = f'{operation_modifiers[-2]}.{operation_modifiers[-1]}'
        expected_operations[key] = 1

    calls_dict = {}
    for c in calls:
        key = c.name
        if key not in calls_dict:
            calls_dict[key] = 0
        calls_dict[key] += 1

    for key in expected_calls:
        assert key in calls_dict
        assert key in expected_calls
        assert calls_dict[key] == expected_calls[key]

    operations_dict = {}
    for o in operations:
        key = o.name
        if key not in operations_dict:
            operations_dict[key] = 0
        operations_dict[key] += 1

    for key in expected_operations:
        assert key in operations_dict
        assert key in expected_operations
        assert operations_dict[key] == expected_operations[key]