fix(rte.rdt): 버전 비교가 자리별 수가 아니라 문자열 순서로 이뤄져 업데이트 판정이 뒤집히는 문제 수정 - #155
Conversation
Version.compareTo() 가 realVersion 을 문자열 사전순으로 비교해 자리가 두 자리 이상이면 순서가 뒤집혔다. 이 비교는 isOlderThan() → TableList.isUpdate() 로 이어지므로 설치본 6.2.9 는 master 6.2.11 로의 업데이트가 목록에 뜨지 않고, 반대로 6.2.11 에는 6.2.9 로의 다운그레이드가 업데이트로 안내됐다. 버전을 . - _ 로 나눠 자리별로 비교하고, 숫자 자리는 수의 크기로 비교하도록 했다. 한쪽에만 있는 자리는 값이 0 이거나 정식 릴리스 한정자(GA/Final/RELEASE)면 없는 것과 같게 보고, SNAPSHOT 같은 한정자면 더 낮은 버전으로 본다.
두 자리 이상 세그먼트(6.2.9 vs 6.2.11), 뒤따르는 0 자리와 릴리스 한정자, SNAPSHOT 순서를 검증한다. 수정 전 Version 에서는 4건 모두 실패한다. compareToKeepsLexicalOrderForLiterals 는 더 이상 사전순이 아니므로 compareToOrdersLiteralVersions 로 이름을 바꿨다. 단언은 그대로다.
한정자끼리는 통째로 문자열 비교를 해 RC9 를 RC10 보다, M2 를 M10 보다 새 버전으로 판정했다. 한정자를 이름과 번호로 나눠 이름이 같으면 번호를 수의 크기로 비교한다. 릴리스보다 뒤에 나오는 SP 한정자도 SNAPSHOT 과 같은 릴리스 이전 한정자로 묶여 1.0.0-SP1 이 1.0.0 보다 낮게 판정됐다. 한정자에 등급(릴리스 이전 < 릴리스 < 릴리스 이후)을 두어 SP 가 붙으면 더 높은 버전으로 본다. compareNumeric 은 BigInteger 비교로 단순화하고, compareTo 가 equals 와 일관되지 않는다는 점을 Javadoc 에 적었다. 한정자 비교와 compareTo 의 반대칭성·추이성 테스트 5건을 추가했다. Refs: #155
|
기여해 주셔서 감사합니다. 재현 표와 Maven 머지한 뒤에, 리뷰 과정에서 확인한 경계 조건들을 후속 커밋 1: 7ad067a (한정자에 붙은 번호, 서비스 팩 한정자)한정자 안의 숫자가 다시 사전순으로 비교되던 문제 한정자끼리는
한정자를 이름과 번호로 나눈 뒤, 이름이 같으면 번호를 수의 크기로 비교하도록 했습니다( 릴리스보다 뒤에 나오는 한정자(SP)가 릴리스보다 낮게 판정되던 문제
그 밖의 변경
후속 커밋 2: 06b1fcf (숫자 자리 수가 다른 버전, 공백이 섞인 버전)자리를 위치만 맞춰 비교해서 한정자가 상대의 숫자 0과 비교되던 문제 본문에 적어 주신
첫 번째 경우는 공백이 섞인 버전이 어떤 버전보다도 낮게 판정되던 문제
테스트 5건 추가: 릴리스 한정자와 끝자리 0의 동등성, 자리 수가 다른 버전의 한정자 정렬, 자리 수가 서로 다른 버전 12종의 연쇄성, 앞뒤 공백, 공백이 섞인 프로퍼티 참조와 프로퍼티 값. "알려진 한계"에 대한 의견
Maven과 의도적으로 다르게 남겨 둔 부분도 참고로 적어 둡니다. 전자정부 표준프레임워크에 기여해 주셔서 감사합니다. |
Version.compareTo 가 자리를 위치만 맞춰 비교해, 숫자 자리 수가 다른 두 버전에서는 한정자가 상대의 숫자 0 과 비교됐다. 4.3.GA 는 4.3 과 같고 4.3 은 4.3.0 과 같은데 4.3.GA 는 4.3.0 보다 낮게 판정돼 추이성이 깨졌고, 1.0-SNAPSHOT 이 1.0.0-SNAPSHOT 보다, 2.0-RC1 이 마스터 pom 에 실제로 있는 2.0.0-M2 보다 낮게 판정됐다. 앞쪽의 숫자 자리들을 먼저 비교하고(없는 자리는 0), 같을 때 그 뒤의 한정자 자리들을 비교한다. GA, Final, RELEASE 는 서로 같은 것으로 본다. pom 에 줄을 바꾸거나 공백을 두고 적은 버전은 첫 자리가 숫자로 인식되지 않아 어떤 버전보다도 낮게 판정됐다. 원본 내용은 그대로 두고 실제 버전과 프로퍼티 해석에서만 앞뒤 공백을 없앤다. Refs: #155
수정 사유 Reason for modification
소스를 수정한 사유가 무엇인지 체크해 주세요. Please check the reason you modified the source. ([X] X는 대문자여야 합니다.)
수정된 소스 내용 Modified source
문제
Version.compareTo()가realVersion.compareTo(...)로 문자열 사전순 비교를 합니다. 버전 자리가 두 자리 이상이 되면 순서가 뒤집힙니다.이 비교는
Version.isOlderThan()→TableList.isOlderThanMaster()→TableList.isUpdate(Service)로 그대로 이어지므로, RDT 서비스 목록의 업데이트 가능 여부 판정이 잘못됩니다.재현 (플러그인이 배포하는 master pom 기준)
egovframework.rte.rdt/src/main/resources/meta/pom_master.xml의spring.framework.version은 현재 6.2.11 입니다.master pom 안의 버전 중 두 자리 이상 자리를 가진 것이 26개라 드문 경우가 아닙니다.
수정
compareTo()가 버전을.-_로 나눈 뒤 자리별로 비교하도록 했습니다.9 < 11). 앞의 0 을 없앤 뒤 자릿수·사전순으로 비교하므로 자리 값이 커도 넘침이 없습니다.0이거나 정식 릴리스 한정자(GA/Final/RELEASE)면 없는 것과 같게 봅니다.4.3 = 4.3.0 = 4.3.0.GA,5.6.15.Final = 5.6.15.SNAPSHOT,alpha,RC1등)가 뒤에 붙으면 더 낮은 버전으로 봅니다.4.3.0-SNAPSHOT < 4.3.0.isOlderThan()의 기존 방어(버전이 없거나 프로퍼티를 해석하지 못하면 판단 유보)는 그대로 두었고,compareTo의 시그니처와 호출부는 바뀌지 않았습니다.JUnit 테스트 JUnit tests
VersionTest15건,DependencyTest5건,PomObjectTest3건,SecureSAXBuilderTest7건이 그대로 통과합니다.Tests run: 19, Failures: 4), 수정 후 19건 전부 통과합니다.pom_master.xml에 실제로 들어 있는 버전 31종의 모든 조합 961쌍을 Maven 의org.apache.maven.artifact.versioning.ComparableVersion과 대조했고 불일치 0건 입니다.compareToKeepsLexicalOrderForLiterals는 더 이상 사전순이 아니므로compareToOrdersLiteralVersions로 이름만 바꿨습니다. 단언은 그대로입니다.알려진 한계
위 961쌍 밖에서, 한정자끼리 순서가 갈리는 두 경우는 Maven 과 다르게 판정합니다.
2.0.0-M2vs2.0-RC1— 자리 수가 서로 달라 정렬이 어긋납니다.1.0.0.RELEASEvs1.0.0— Maven 은RELEASE를 릴리스 별칭으로 보지 않아 더 높은 버전으로 판정합니다. 이 플러그인의 용도(설치본이 master 보다 낮은지 판정)에서는 Spring 계열의x.y.z.RELEASE를 같은 버전으로 보는 편이 안전하다고 판단해 의도적으로 같게 두었습니다.다르게 보시는 편이 맞다면 알려주시면 맞추겠습니다.
테스트 브라우저 Test Browser
Eclipse 플러그인(RCP) 코드라 브라우저가 관여하지 않습니다. JDK 21 · JUnit 4.7 로 테스트했습니다.
테스트 스크린샷 또는 캡처 영상 Test screenshots or captured video
UI 화면이 아닌 순수 판정 로직이라 스크린샷 대신 테스트 실행 결과로 갈음합니다.