Page Menu
Home
Software Heritage
Search
Configure Global Search
Log In
Files
F9339407
test_diff.py
No One
Temporary
Actions
Download File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Award Token
Flag For Later
Size
14 KB
Subscribers
None
test_diff.py
View Options
# Copyright (C) 2018 The Software Heritage developers
# See the AUTHORS file at the top-level directory of this distribution
# License: GNU General Public License version 3, or any later version
# See top-level LICENSE file for more information
# flake8: noqa
import
unittest
from
nose.tools
import
istest
,
nottest
from
unittest.mock
import
patch
from
swh.model.hashutil
import
hash_to_bytes
from
swh.model.identifiers
import
directory_identifier
from
swh.storage.algos
import
diff
class
DirectoryModel
(
object
):
"""
Quick and dirty directory model to ease the writing
of revision trees differential tests.
"""
def
__init__
(
self
,
name
=
''
):
self
.
data
=
{}
self
.
data
[
'name'
]
=
name
self
.
data
[
'perms'
]
=
16384
self
.
data
[
'type'
]
=
'dir'
self
.
data
[
'entries'
]
=
[]
self
.
data
[
'entry_idx'
]
=
{}
def
__getitem__
(
self
,
item
):
if
item
==
'target'
:
return
hash_to_bytes
(
directory_identifier
(
self
))
else
:
return
self
.
data
[
item
]
def
add_file
(
self
,
path
,
sha1
=
None
):
path_parts
=
path
.
split
(
b
'/'
)
if
len
(
path_parts
)
==
1
:
self
[
'entry_idx'
][
path
]
=
len
(
self
[
'entries'
])
self
[
'entries'
]
.
append
({
'target'
:
hash_to_bytes
(
sha1
),
'name'
:
path
,
'perms'
:
33188
,
'type'
:
'file'
})
else
:
if
not
path_parts
[
0
]
in
self
[
'entry_idx'
]:
self
[
'entry_idx'
][
path_parts
[
0
]]
=
len
(
self
[
'entries'
])
self
[
'entries'
]
.
append
(
DirectoryModel
(
path_parts
[
0
]))
if
path_parts
[
1
]:
dir_idx
=
self
[
'entry_idx'
][
path_parts
[
0
]]
self
[
'entries'
][
dir_idx
]
.
add_file
(
b
'/'
.
join
(
path_parts
[
1
:]),
sha1
)
def
get_hash_data
(
self
,
entry_hash
):
if
self
[
'target'
]
==
entry_hash
:
ret
=
[]
for
e
in
self
[
'entries'
]:
ret
.
append
({
'target'
:
e
[
'target'
],
'name'
:
e
[
'name'
],
'perms'
:
e
[
'perms'
],
'type'
:
e
[
'type'
]
})
return
ret
else
:
for
e
in
self
[
'entries'
]:
if
e
[
'type'
]
==
'file'
and
e
[
'target'
]
==
entry_hash
:
return
e
elif
e
[
'type'
]
==
'dir'
:
data
=
e
.
get_hash_data
(
entry_hash
)
if
data
:
return
data
return
None
def
get_path_data
(
self
,
path
):
path_parts
=
path
.
split
(
b
'/'
)
entry_idx
=
self
[
'entry_idx'
][
path_parts
[
0
]]
entry
=
self
[
'entries'
][
entry_idx
]
if
len
(
path_parts
)
==
1
:
return
{
'target'
:
entry
[
'target'
],
'name'
:
entry
[
'name'
],
'perms'
:
entry
[
'perms'
],
'type'
:
entry
[
'type'
]
}
else
:
return
entry
.
get_path_data
(
b
'/'
.
join
(
path_parts
[
1
:]))
@patch
(
'swh.storage.algos.diff._get_rev'
)
@patch
(
'swh.storage.algos.dir_iterators._get_dir'
)
class
TestDiffRevisions
(
unittest
.
TestCase
):
@nottest
def
diff_revisions
(
self
,
rev_from
,
rev_to
,
from_dir_model
,
to_dir_model
,
expected_changes
,
mock_get_dir
,
mock_get_rev
):
rev_from_bytes
=
hash_to_bytes
(
rev_from
)
rev_to_bytes
=
hash_to_bytes
(
rev_to
)
def
_get_rev
(
*
args
,
**
kwargs
):
if
args
[
1
]
==
rev_from_bytes
:
return
{
'directory'
:
from_dir_model
[
'target'
]}
else
:
return
{
'directory'
:
to_dir_model
[
'target'
]}
def
_get_dir
(
*
args
,
**
kwargs
):
from_dir
=
from_dir_model
.
get_hash_data
(
args
[
1
])
to_dir
=
to_dir_model
.
get_hash_data
(
args
[
1
])
return
from_dir
if
from_dir
!=
None
else
to_dir
mock_get_rev
.
side_effect
=
_get_rev
mock_get_dir
.
side_effect
=
_get_dir
changes
=
diff
.
diff_revisions
(
None
,
rev_from_bytes
,
rev_to_bytes
,
track_renaming
=
True
)
self
.
assertEqual
(
changes
,
expected_changes
)
@istest
def
test_insert_delete
(
self
,
mock_get_dir
,
mock_get_rev
):
rev_from
=
'898ff03e1e7925ecde3da66327d3cdc7e07625ba'
rev_to
=
'647c3d381e67490e82cdbbe6c96e46d5e1628ce2'
from_dir_model
=
DirectoryModel
()
to_dir_model
=
DirectoryModel
()
to_dir_model
.
add_file
(
b
'file1'
,
'ea15f54ca215e7920c60f564315ebb7f911a5204'
)
to_dir_model
.
add_file
(
b
'file2'
,
'3e5faecb3836ffcadf82cc160787e35d4e2bec6a'
)
to_dir_model
.
add_file
(
b
'file3'
,
'2ae33b2984974d35eababe4890d37fbf4bce6b2c'
)
expected_changes
=
\
[{
'type'
:
'insert'
,
'from'
:
None
,
'from_path'
:
None
,
'to'
:
to_dir_model
.
get_path_data
(
b
'file1'
),
'to_path'
:
b
'file1'
},
{
'type'
:
'insert'
,
'from'
:
None
,
'from_path'
:
None
,
'to'
:
to_dir_model
.
get_path_data
(
b
'file2'
),
'to_path'
:
b
'file2'
},
{
'type'
:
'insert'
,
'from'
:
None
,
'from_path'
:
None
,
'to'
:
to_dir_model
.
get_path_data
(
b
'file3'
),
'to_path'
:
b
'file3'
}]
self
.
diff_revisions
(
rev_from
,
rev_to
,
from_dir_model
,
to_dir_model
,
expected_changes
,
mock_get_dir
,
mock_get_rev
)
from_dir_model
=
DirectoryModel
()
from_dir_model
.
add_file
(
b
'file1'
,
'ea15f54ca215e7920c60f564315ebb7f911a5204'
)
from_dir_model
.
add_file
(
b
'file2'
,
'3e5faecb3836ffcadf82cc160787e35d4e2bec6a'
)
from_dir_model
.
add_file
(
b
'file3'
,
'2ae33b2984974d35eababe4890d37fbf4bce6b2c'
)
to_dir_model
=
DirectoryModel
()
expected_changes
=
\
[{
'type'
:
'delete'
,
'from'
:
from_dir_model
.
get_path_data
(
b
'file1'
),
'from_path'
:
b
'file1'
,
'to'
:
None
,
'to_path'
:
None
},
{
'type'
:
'delete'
,
'from'
:
from_dir_model
.
get_path_data
(
b
'file2'
),
'from_path'
:
b
'file2'
,
'to'
:
None
,
'to_path'
:
None
},
{
'type'
:
'delete'
,
'from'
:
from_dir_model
.
get_path_data
(
b
'file3'
),
'from_path'
:
b
'file3'
,
'to'
:
None
,
'to_path'
:
None
}]
self
.
diff_revisions
(
rev_from
,
rev_to
,
from_dir_model
,
to_dir_model
,
expected_changes
,
mock_get_dir
,
mock_get_rev
)
@istest
def
test_onelevel_diff
(
self
,
mock_get_dir
,
mock_get_rev
):
rev_from
=
'898ff03e1e7925ecde3da66327d3cdc7e07625ba'
rev_to
=
'647c3d381e67490e82cdbbe6c96e46d5e1628ce2'
from_dir_model
=
DirectoryModel
()
from_dir_model
.
add_file
(
b
'file1'
,
'ea15f54ca215e7920c60f564315ebb7f911a5204'
)
from_dir_model
.
add_file
(
b
'file2'
,
'f4a96b2000be83b61254d107046fa9777b17eb34'
)
from_dir_model
.
add_file
(
b
'file3'
,
'd3c00f9396c6d0277727cec522ff6ad1ea0bc2da'
)
to_dir_model
=
DirectoryModel
()
to_dir_model
.
add_file
(
b
'file2'
,
'3ee0f38ee0ea23cc2c8c0b9d66b27be4596b002b'
)
to_dir_model
.
add_file
(
b
'file3'
,
'd3c00f9396c6d0277727cec522ff6ad1ea0bc2da'
)
to_dir_model
.
add_file
(
b
'file4'
,
'40460b9653b1dc507e1b6eb333bd4500634bdffc'
)
expected_changes
=
\
[{
'type'
:
'delete'
,
'from'
:
from_dir_model
.
get_path_data
(
b
'file1'
),
'from_path'
:
b
'file1'
,
'to'
:
None
,
'to_path'
:
None
},
{
'type'
:
'modify'
,
'from'
:
from_dir_model
.
get_path_data
(
b
'file2'
),
'from_path'
:
b
'file2'
,
'to'
:
to_dir_model
.
get_path_data
(
b
'file2'
),
'to_path'
:
b
'file2'
},
{
'type'
:
'insert'
,
'from'
:
None
,
'from_path'
:
None
,
'to'
:
to_dir_model
.
get_path_data
(
b
'file4'
),
'to_path'
:
b
'file4'
}]
self
.
diff_revisions
(
rev_from
,
rev_to
,
from_dir_model
,
to_dir_model
,
expected_changes
,
mock_get_dir
,
mock_get_rev
)
@istest
def
test_twolevels_diff
(
self
,
mock_get_dir
,
mock_get_rev
):
rev_from
=
'898ff03e1e7925ecde3da66327d3cdc7e07625ba'
rev_to
=
'647c3d381e67490e82cdbbe6c96e46d5e1628ce2'
from_dir_model
=
DirectoryModel
()
from_dir_model
.
add_file
(
b
'file1'
,
'ea15f54ca215e7920c60f564315ebb7f911a5204'
)
from_dir_model
.
add_file
(
b
'dir1/file1'
,
'8335fca266811bac7ae5c8e1621476b4cf4156b6'
)
from_dir_model
.
add_file
(
b
'dir1/file2'
,
'a6127d909e79f1fcb28bbf220faf86e7be7831e5'
)
from_dir_model
.
add_file
(
b
'dir1/file3'
,
'18049b8d067ce1194a7e1cce26cfa3ae4242a43d'
)
from_dir_model
.
add_file
(
b
'file2'
,
'd3c00f9396c6d0277727cec522ff6ad1ea0bc2da'
)
to_dir_model
=
DirectoryModel
()
to_dir_model
.
add_file
(
b
'file1'
,
'3ee0f38ee0ea23cc2c8c0b9d66b27be4596b002b'
)
to_dir_model
.
add_file
(
b
'dir1/file2'
,
'de3548b32a8669801daa02143a66dae21fe852fd'
)
to_dir_model
.
add_file
(
b
'dir1/file3'
,
'18049b8d067ce1194a7e1cce26cfa3ae4242a43d'
)
to_dir_model
.
add_file
(
b
'dir1/file4'
,
'f5c3f42aec5fe7b92276196c350cbadaf4c51f87'
)
to_dir_model
.
add_file
(
b
'file2'
,
'd3c00f9396c6d0277727cec522ff6ad1ea0bc2da'
)
expected_changes
=
\
[{
'type'
:
'delete'
,
'from'
:
from_dir_model
.
get_path_data
(
b
'dir1/file1'
),
'from_path'
:
b
'dir1/file1'
,
'to'
:
None
,
'to_path'
:
None
},
{
'type'
:
'modify'
,
'from'
:
from_dir_model
.
get_path_data
(
b
'dir1/file2'
),
'from_path'
:
b
'dir1/file2'
,
'to'
:
to_dir_model
.
get_path_data
(
b
'dir1/file2'
),
'to_path'
:
b
'dir1/file2'
},
{
'type'
:
'insert'
,
'from'
:
None
,
'from_path'
:
None
,
'to'
:
to_dir_model
.
get_path_data
(
b
'dir1/file4'
),
'to_path'
:
b
'dir1/file4'
},
{
'type'
:
'modify'
,
'from'
:
from_dir_model
.
get_path_data
(
b
'file1'
),
'from_path'
:
b
'file1'
,
'to'
:
to_dir_model
.
get_path_data
(
b
'file1'
),
'to_path'
:
b
'file1'
}]
self
.
diff_revisions
(
rev_from
,
rev_to
,
from_dir_model
,
to_dir_model
,
expected_changes
,
mock_get_dir
,
mock_get_rev
)
@istest
def
test_insert_delete_empty_dirs
(
self
,
mock_get_dir
,
mock_get_rev
):
rev_from
=
'898ff03e1e7925ecde3da66327d3cdc7e07625ba'
rev_to
=
'647c3d381e67490e82cdbbe6c96e46d5e1628ce2'
from_dir_model
=
DirectoryModel
()
from_dir_model
.
add_file
(
b
'dir3/file1'
,
'ea15f54ca215e7920c60f564315ebb7f911a5204'
)
to_dir_model
=
DirectoryModel
()
to_dir_model
.
add_file
(
b
'dir3/file1'
,
'ea15f54ca215e7920c60f564315ebb7f911a5204'
)
to_dir_model
.
add_file
(
b
'dir3/dir1/'
)
expected_changes
=
\
[{
'type'
:
'insert'
,
'from'
:
None
,
'from_path'
:
None
,
'to'
:
to_dir_model
.
get_path_data
(
b
'dir3/dir1'
),
'to_path'
:
b
'dir3/dir1'
}]
self
.
diff_revisions
(
rev_from
,
rev_to
,
from_dir_model
,
to_dir_model
,
expected_changes
,
mock_get_dir
,
mock_get_rev
)
from_dir_model
=
DirectoryModel
()
from_dir_model
.
add_file
(
b
'dir1/dir2/'
)
from_dir_model
.
add_file
(
b
'dir1/file1'
,
'ea15f54ca215e7920c60f564315ebb7f911a5204'
)
to_dir_model
=
DirectoryModel
()
to_dir_model
.
add_file
(
b
'dir1/file1'
,
'ea15f54ca215e7920c60f564315ebb7f911a5204'
)
expected_changes
=
\
[{
'type'
:
'delete'
,
'from'
:
from_dir_model
.
get_path_data
(
b
'dir1/dir2'
),
'from_path'
:
b
'dir1/dir2'
,
'to'
:
None
,
'to_path'
:
None
}]
self
.
diff_revisions
(
rev_from
,
rev_to
,
from_dir_model
,
to_dir_model
,
expected_changes
,
mock_get_dir
,
mock_get_rev
)
@istest
def
test_track_renaming
(
self
,
mock_get_dir
,
mock_get_rev
):
rev_from
=
'898ff03e1e7925ecde3da66327d3cdc7e07625ba'
rev_to
=
'647c3d381e67490e82cdbbe6c96e46d5e1628ce2'
from_dir_model
=
DirectoryModel
()
from_dir_model
.
add_file
(
b
'file1_oldname'
,
'ea15f54ca215e7920c60f564315ebb7f911a5204'
)
from_dir_model
.
add_file
(
b
'dir1/file1_oldname'
,
'ea15f54ca215e7920c60f564315ebb7f911a5204'
)
from_dir_model
.
add_file
(
b
'file2_oldname'
,
'd3c00f9396c6d0277727cec522ff6ad1ea0bc2da'
)
to_dir_model
=
DirectoryModel
()
to_dir_model
.
add_file
(
b
'dir1/file1_newname'
,
'ea15f54ca215e7920c60f564315ebb7f911a5204'
)
to_dir_model
.
add_file
(
b
'dir2/file1_newname'
,
'ea15f54ca215e7920c60f564315ebb7f911a5204'
)
to_dir_model
.
add_file
(
b
'file2_newname'
,
'd3c00f9396c6d0277727cec522ff6ad1ea0bc2da'
)
expected_changes
=
\
[{
'type'
:
'rename'
,
'from'
:
from_dir_model
.
get_path_data
(
b
'dir1/file1_oldname'
),
'from_path'
:
b
'dir1/file1_oldname'
,
'to'
:
to_dir_model
.
get_path_data
(
b
'dir1/file1_newname'
),
'to_path'
:
b
'dir1/file1_newname'
},
{
'type'
:
'rename'
,
'from'
:
from_dir_model
.
get_path_data
(
b
'file1_oldname'
),
'from_path'
:
b
'file1_oldname'
,
'to'
:
to_dir_model
.
get_path_data
(
b
'dir2/file1_newname'
),
'to_path'
:
b
'dir2/file1_newname'
},
{
'type'
:
'rename'
,
'from'
:
from_dir_model
.
get_path_data
(
b
'file2_oldname'
),
'from_path'
:
b
'file2_oldname'
,
'to'
:
to_dir_model
.
get_path_data
(
b
'file2_newname'
),
'to_path'
:
b
'file2_newname'
}]
self
.
diff_revisions
(
rev_from
,
rev_to
,
from_dir_model
,
to_dir_model
,
expected_changes
,
mock_get_dir
,
mock_get_rev
)
File Metadata
Details
Attached
Mime Type
text/x-python
Expires
Jul 4 2025, 9:40 AM (5 w, 5 d ago)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
3337974
Attached To
rDSTO Storage manager
Event Timeline
Log In to Comment