Skip to content

fix: ShellScriptSupport.isUnix()가 AIX에서 항상 false를 반환하는 문제 수정 - #333

Open
wantaekchoi wants to merge 1 commit into
eGovFramework:mainfrom
wantaekchoi:fix/shell-script-support-aix-detection
Open

fix: ShellScriptSupport.isUnix()가 AIX에서 항상 false를 반환하는 문제 수정#333
wantaekchoi wants to merge 1 commit into
eGovFramework:mainfrom
wantaekchoi:fix/shell-script-support-aix-detection

Conversation

@wantaekchoi

Copy link
Copy Markdown
Contributor

수정 사유 Reason for modification

  • 버그수정 Bug fixes
  • 기능개선 Enhancements
  • 기능추가 Adding features
  • 기타 Others

수정된 소스 내용 Modified source

ShellScriptSupport.isUnix() 한 줄 안에서 세 비교가 서로 다릅니다.

return (OS.indexOf("nix") >= 0 || OS.indexOf("nux") >= 0 || OS.indexOf("aix") > 0);
                          ^^^^                      ^^^^                      ^^^

AIX의 os.name"AIX"이므로 소문자화하면 "aix"가 되고 indexOf0을 돌려줍니다. > 0이라 이 조건은 성립할 수 없습니다. 즉 "aix" 토큰은 자기가 매칭할 수 있는 유일한 문자열에 대해 죽어 있습니다.

같은 판정이 로케일에도 걸립니다. OS는 인자 없는 toLowerCase()로 만들어지는데, 터키어·아제르바이잔어 로케일에서 "AIX"는 점 없는 ı가 섞인 "aıx"가 되어 indexOf("aix")가 -1이 됩니다. >= 0으로 고쳐도 그 로케일에서는 여전히 못 찾습니다. 두 원인이 같은 판정 하나에 겹쳐 있어 함께 고쳤습니다.

AS-IS

private static String OS = System.getProperty("os.name").toLowerCase();
...
return (OS.indexOf("nix") >= 0 || OS.indexOf("nux") >= 0 || OS.indexOf("aix") > 0);

TO-BE

private static String OS = System.getProperty("os.name").toLowerCase(Locale.ROOT);
...
return (OS.indexOf("nix") >= 0 || OS.indexOf("nux") >= 0 || OS.indexOf("aix") >= 0);

같은 결함 클래스를 Locale.ROOT로 고친 선례가 이 저장소에 있습니다 — DefaultMapUserDetailsMapping의 컬럼명 소문자화(#321).

영향 범위

isWindows()·isMac()·isSolaris()의 판정은 그대로입니다. 바뀌는 것은 AIX에서 isUnix()가 이제 true를 돌려준다는 점뿐입니다.

JUnit 테스트 JUnit tests

  • JUnit 테스트 JUnit tests
  • 수동 테스트 Manual testing

ShellScriptSupportOsTest 2건을 추가했습니다. OS 필드는 클래스 로드 시 한 번만 채워지므로, 리플렉션으로 값을 바꿔 판정 로직만 확인하고 finally에서 되돌립니다.

수정 지점만 되돌린 상태(RED)

[ERROR] Tests run: 2, Failures: 1, Errors: 0, Skipped: 0
[ERROR]   ShellScriptSupportOsTest.isUnixOnAix
          os.name이 AIX면 isUnix()가 true여야 한다 ==> expected: <true> but was: <false>

수정 후(GREEN, 모듈 전체)

[INFO] Tests run: 76, Failures: 0, Errors: 0, Skipped: 0
[INFO] BUILD SUCCESS

로케일 쪽은 OS가 이미 채워진 뒤라 같은 방식으로 재현할 수 없어 테스트가 덮지 못합니다.

한 줄 안에서 세 비교가 서로 다르다.

  return (OS.indexOf("nix") >= 0 || OS.indexOf("nux") >= 0 || OS.indexOf("aix") > 0);

AIX의 os.name은 "AIX"이므로 소문자화하면 "aix"가 되고 indexOf는 0을 돌려준다.
> 0 이라 이 조건은 성립할 수 없다. 형제 두 비교는 >= 0을 쓴다. 즉 "aix" 토큰은
자기가 매칭할 수 있는 유일한 문자열에 대해 죽어 있다.

같은 메서드가 로케일에도 걸린다. OS는 인자 없는 toLowerCase()로 만들어지는데,
터키어·아제르바이잔어 로케일에서 "AIX"는 점 없는 ı가 섞인 "aıx"가 되어
indexOf("aix")가 -1이 된다. >= 0으로 고쳐도 그 로케일에서는 여전히 못 찾는다.
두 원인이 같은 판정 하나에 겹쳐 있어 함께 고쳤다.

같은 결함 클래스를 Locale.ROOT로 고친 선례가 이 저장소에 있다 —
DefaultMapUserDetailsMapping의 컬럼명 소문자화(eGovFramework#321).

OS 필드는 클래스 로드 시 한 번만 채워지므로, 테스트는 리플렉션으로 값을 바꿔
판정 로직만 확인하고 원래 값으로 되돌린다. 로케일 쪽은 필드가 이미 채워진 뒤라
같은 방식으로 재현할 수 없어 테스트가 덮지 못한다.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant