Files
game-cards/addons/gut/test/unit/test_update_detector.gd
2026-05-29 09:16:10 +08:00

490 lines
12 KiB
GDScript

extends GutTest
var UpdateDetector = GutUtils.UpdateDetector
var _sample_parsed_data = {
"asset_library":"99.0",
"branches":{
"main":{
"godot_min":"8.0.0",
"godot_max":"8.999"
}
},
"releases":{
"99.0":{
"godot_min":"9.0.0",
"godot_max":"9999"
},
"13.2.0":{
"godot_min":"3.6.5",
"godot_max":"3.999",
},
"13.1.0":{
"godot_min":"3.6.0",
"godot_max":"3.999",
},
"13.0.0":{
"godot_min":"3.0.0",
"godot_max":"3.5.0",
},
"12.0":{
"godot_min":"2.0",
"godot_max":"2.999"
},
"11.0":{
"godot_min":"1.0",
"godot_max":"1.999"
}
}
}
func get_sample_data():
return _sample_parsed_data.duplicate(true)
func test_can_make_one():
var ud = UpdateDetector.new()
assert_not_null(ud)
ud.free()
var _vdata = ParameterFactory.named_parameters([
'godot_version', 'expected_gut_version'
],[
["1.0", "11.0"],
["2.0", "12.0"],
["3.0.0", "13.0.0"],
["3.4.1", "13.0.0"],
["3.6.0", "13.1.0"],
["3.6.4", "13.1.0"],
["3.6.5", "13.2.0"],
["3.6.7", "13.2.0"],
["9", "99.0"],
["99", "99.0"],
["999", "99.0"],
["0.0.1", "0.0.0"],
["999999", "0.0.0"]
])
func test_get_recommented_gut_version_from_sample_data(data=use_parameters(_vdata)):
var ud = autofree(UpdateDetector.new())
ud.parse_version_data(get_sample_data())
var v = ud.get_gut_version_for_godot_version(data.godot_version)
assert_eq(v, data.expected_gut_version, str('rec version for ', data.godot_version))
var _valid_data = ParameterFactory.named_parameters([
'gut_version', 'godot_version', 'expected'
],[
["11.0", "1.0.0", true],
["11.0", "2.0", false]
])
func test_is_gut_version_valid_for_godot_version(data=use_parameters(_valid_data)):
var ud = autofree(UpdateDetector.new())
ud.parse_version_data(get_sample_data())
var is_it = ud.is_gut_version_valid(data.gut_version, data.godot_version)
assert_eq(is_it, data.expected, str(data.gut_version, ' valid for ', data.godot_version))
func test_parse_data_returns_dictionary():
var ud = autofree(UpdateDetector.new())
var data = """{
"asset_library":"x.x",
"branches":{},
"releases":{
"99.0":{
"godot_min":"9.0.0",
"godot_max":"9999"
},
}
}"""
ud.parse_version_data(data)
assert_typeof(ud.parsed_data, TYPE_DICTIONARY)
func test_missing_godot_min_listed_as_issue():
var ud = autofree(UpdateDetector.new())
var data = """{
"asset_library":"x.x",
"branches":{},
"releases":{
"99.0":{
"godot_max":"9999"
}
}
}"""
ud.parse_version_data(data)
assert_eq(ud.data_issues.size(), 1)
if(is_failing()):
gut.p(str("Issues\n", ud.data_issues))
func test_missing_godot_max_listed_as_issue():
var ud = autofree(UpdateDetector.new())
var data = """{
"asset_library":"x.x",
"branches":{},
"releases":{
"99.0":{
"godot_min":"9.0.0",
}
}
}"""
ud.parse_version_data(data)
assert_eq(ud.data_issues.size(), 1)
func test_missing_releases_listed_as_issue():
var ud = autofree(UpdateDetector.new())
var data = """{
"asset_library":"x.x",
"branches":{}
}"""
ud.parse_version_data(data)
assert_eq(ud.data_issues.size(), 1)
func test_when_gut_version_not_found():
var ud = autofree(UpdateDetector.new())
ud.parse_version_data(get_sample_data())
assert_eq(ud.get_gut_version_for_godot_version("3.6.7"), "13.2.0")
func test_when_godot_version_not_found_branches_is_checked():
var ud = autofree(UpdateDetector.new())
ud.parse_version_data(get_sample_data())
assert_eq(ud.get_gut_version_for_godot_version("8.0.0"), "main")
func test_missing_branches_entry_is_an_issue():
var ud = autofree(UpdateDetector.new())
var data = """{
"asset_library":"x.x",
"releases":{
"99.0":{
"godot_min":"9.0.0",
"godot_max":"9999"
}
}
}"""
ud.parse_version_data(data)
assert_eq(ud.data_issues.size(), 1)
func test_branches_missing_godot_min_is_an_issue():
var ud = autofree(UpdateDetector.new())
var data = """{
"asset_library":"x.x",
"releases":{},
"branches":{
"some_branch":{
"godot_max":"9999"
}
}
}"""
ud.parse_version_data(data)
assert_eq(ud.data_issues.size(), 1)
func test_branches_missing_godot_max_is_an_issue():
var ud = autofree(UpdateDetector.new())
var data = """{
"asset_library":"x.x",
"releases":{},
"branches":{
"some_branch":{
"godot_min":"9.0.0",
}
}
}"""
ud.parse_version_data(data)
assert_eq(ud.data_issues.size(), 1)
func test_when_gut_version_not_found_is_valid_returns_false():
var ud = autofree(UpdateDetector.new())
ud.parse_file(ud.LOCAL_FILE_PATH)
assert_false(ud.is_gut_version_valid('23432.124231.123234', GutUtils.godot_version_string()))
func test_when_asset_library_entry_is_missing_it_is_an_issue():
var ud = autofree(UpdateDetector.new())
var data = """{
"releases":{},
"branches":{}
}"""
ud.parse_version_data(data)
assert_eq(ud.data_issues.size(), 1)
func test_is_in_asset_library_returns_true_for_gut_version_in_entry():
var ud = autofree(UpdateDetector.new())
ud.parse_version_data(get_sample_data())
assert_true(ud.is_in_asset_library("99.0"))
func test_is_in_asset_library_returns_false_for_gut_version_not_in_entry():
var ud = autofree(UpdateDetector.new())
ud.parse_version_data(get_sample_data())
assert_false(ud.is_in_asset_library("22.0"))
func test_if_asset_library_is_missing_is_in_asset_library_returns_false():
var ud = autofree(UpdateDetector.new())
var data = get_sample_data().duplicate()
data.erase("asset_library")
ud.parse_version_data(data)
assert_false(ud.is_in_asset_library("99.0"))
func test_if_later_version_comes_after_current_verions_it_still_finds_later_version():
var data = {
"asset_library":"99.0",
"branches":{},
"releases":{
"9.6.0": {
"godot_max": "999",
"godot_min": "4.6"
},
"9.6.1": {
"godot_max": "999",
"godot_min": "4.6"
}
}}
var ud = autofree(UpdateDetector.new())
ud.parse_version_data(data)
assert_eq(ud.get_gut_version_for_godot_version('4.6'), '9.6.1')
class TestFetch:
extends GutTest
var _sample_parsed_data = {
"asset_library":"99.0",
"branches":{
"main":{
"godot_min":"8.0.0",
"godot_max":"8.999"
}
},
"releases":{
"99.0":{
"godot_min":"9.0.0",
"godot_max":"9999"
},
"13.2.0":{
"godot_min":"3.6.5",
"godot_max":"3.999",
},
}
}
func get_sample_data():
return _sample_parsed_data.duplicate(true)
var UpdateDetector = GutUtils.UpdateDetector
func before_each():
gut.file_delete(UpdateDetector.REMOTE_FILE_PATH)
func _create_update_detector():
var to_return = partial_double(UpdateDetector).new()
var d_http_request = partial_double(HTTPRequest).new()
add_child_autofree(to_return)
to_return._http_request.free()
to_return._setup_http_request(d_http_request)
return to_return
func _data_as_pba(data=get_sample_data()):
return JSON.stringify(data).to_utf8_buffer()
func test_when_rc_200_returned_file_written():
var ud = _create_update_detector()
stub(ud.fetch_remote_file).to_do_nothing()
ud._http_request.request_completed.emit('result', 200, '', _data_as_pba())
assert_file_exists(ud.REMOTE_FILE_PATH)
func test_when_rc_200_not_returned_file_not_written():
var ud = _create_update_detector()
stub(ud.fetch_remote_file).to_do_nothing()
ud._http_request.request_completed.emit('result', 300, '', _data_as_pba())
assert_file_does_not_exist(ud.REMOTE_FILE_PATH)
assert_push_error("Response code")
func test_when_rc_200_data_is_parsed():
var ud = _create_update_detector()
stub(ud.fetch_remote_file).to_do_nothing()
ud._http_request.request_completed.emit('result', 200, '',
JSON.stringify(get_sample_data()).to_utf8_buffer())
assert_eq(ud.parsed_data, get_sample_data())
func test_when_there_issues_with_the_data_the_file_is_not_written():
var ud = _create_update_detector()
var data = get_sample_data()
data.erase('asset_library')
data = JSON.stringify(data).to_utf8_buffer()
ud._http_request.request_completed.emit('result', 200, '', data)
assert_file_does_not_exist(ud.REMOTE_FILE_PATH)
assert_push_error("nvalid version data")
func test_when_there_are_issues_with_the_data_parsed_data_is_empty():
var ud = _create_update_detector()
var data = get_sample_data()
data.erase('asset_library')
data = JSON.stringify(data).to_utf8_buffer()
ud._http_request.request_completed.emit('result', 200, '', data)
assert_eq(ud.parsed_data, {})
assert_push_error("nvalid version data")
func test_when_json_is_invalid_it_is_an_issue():
var ud = _create_update_detector()
var data = get_sample_data()
data.erase('asset_library')
data = "{invalid json}".to_utf8_buffer()
ud._http_request.request_completed.emit('result', 200, '', data)
assert_push_error("Invalid JSON")
func test_when_json_is_invalid_dowanlod_signal_emitted():
var ud = _create_update_detector()
watch_signals(ud)
var data = get_sample_data()
data.erase('asset_library')
data = "{invalid json}".to_utf8_buffer()
ud._http_request.request_completed.emit('result', 200, '', data)
assert_signal_emitted(ud.download_completed)
assert_push_error("Invalid JSON")
func test_fetched_data_is_written_with_fetch_timestamp():
var ud = _create_update_detector()
stub(ud.fetch_remote_file).to_do_nothing()
ud._http_request.request_completed.emit('result', 200, '', _data_as_pba())
var json_text = FileAccess.get_file_as_string(ud.REMOTE_FILE_PATH)
var json = JSON.parse_string(json_text)
assert_has(json, 'fetch_timestamp')
class TestCheckForUpdateWithFetch:
extends GutTest
var _sample_parsed_data = {
"asset_library":"99.0",
"branches":{
"main":{
"godot_min":"8.0.0",
"godot_max":"8.999"
}
},
"releases":{
"99.0":{
"godot_min":"9.0.0",
"godot_max":"9999"
},
"13.2.0":{
"godot_min":"3.6.5",
"godot_max":"3.999",
},
}
}
func before_each():
gut.file_delete(UpdateDetector.REMOTE_FILE_PATH)
func get_sample_data():
return _sample_parsed_data.duplicate(true)
func _create_update_detector():
var to_return = partial_double(UpdateDetector).new()
var d_http_request = partial_double(HTTPRequest).new()
add_child_autofree(to_return)
to_return._http_request.free()
to_return._setup_http_request(d_http_request)
return to_return
var UpdateDetector = GutUtils.UpdateDetector
func test_it_fetches_data_by_default():
var ud = _create_update_detector()
stub(ud.fetch_remote_file).to_do_nothing()
ud.check_for_update_with_fetch()
assert_called(ud.fetch_remote_file)
func test_when_last_fetch_is_not_later_than_min_fetch_time_fetch_is_not_called():
var ud = _create_update_detector()
stub(ud.fetch_remote_file).to_do_nothing()
ud.min_fetch_wait = 60 * 60 * 24 * 10_000 # ten thousand days
var fake_last_fetch = get_sample_data()
fake_last_fetch.fetch_timestamp = Time.get_unix_time_from_system()
GutUtils.write_file(ud.REMOTE_FILE_PATH, JSON.stringify(fake_last_fetch))
ud.check_for_update_with_fetch()
assert_not_called(ud.fetch_remote_file)
func test_when_last_fetch_outside_bounds_then_fetch_is_called():
var ud = _create_update_detector()
stub(ud.fetch_remote_file).to_do_nothing()
ud.min_fetch_wait = 0
var fake_last_fetch = get_sample_data()
fake_last_fetch.fetch_timestamp = Time.get_unix_time_from_system() - (60 * 60)
GutUtils.write_file(ud.REMOTE_FILE_PATH, JSON.stringify(fake_last_fetch))
ud.check_for_update_with_fetch()
assert_called(ud.fetch_remote_file)
func test_check_for_update_with_fetch_emits_updated_upon_completion():
var ud = _create_update_detector()
stub(ud.fetch_remote_file).to_call(func():
ud.download_completed.emit.call_deferred())
ud.check_for_update_with_fetch()
await wait_for_signal(ud.updated, 2)
assert_signal_emitted(ud.updated)
func test_check_for_update_with_fetch_can_be_forced_to_fetch():
var ud = _create_update_detector()
stub(ud.fetch_remote_file).to_do_nothing()
ud.min_fetch_wait = 60 * 60 * 24 * 10_000 # ten thousand days
var fake_last_fetch = get_sample_data()
fake_last_fetch.fetch_timestamp = Time.get_unix_time_from_system()
GutUtils.write_file(ud.REMOTE_FILE_PATH, JSON.stringify(fake_last_fetch))
ud.check_for_update_with_fetch(true)
assert_called(ud.fetch_remote_file)