finding the current test method


테스트 메서드 하나가 끝나지 않고 계속 도는 듯 하다. 어떤 클래스의 어떤 메서드인지 다음과 같이 리스너를 하나 만들어서 사용했다.

public class InvokedMethodListener implements IInvokedMethodListener {

    @Override
    public void beforeInvocation(final IInvokedMethod method,
                                 final ITestResult result) {
        logger.debug("beforeInvocation({}, {})", method, result);
    }

    @Override
    public void afterInvocation(final IInvokedMethod method,
                                final ITestResult result) {
        // not interested
    }
}
<plugin>
  <groupId>org.apache.maven.plugins</groupId>
  <artifactId>maven-surefire-plugin</artifactId>
  <configuration>
    <properties>
      <property>
        <name>listeners</name>
        <value>package.to.the.InvokedMethodListener</value>
      </property>
    </properties>
  </configuration>
</plugin>
HH.mm.ss.SSS [main] DEBUG package.to.the.InvokedMethodListener - beforeInvocation(...)

Dependencies for JavaMail


references

/:project/:dependencies

<dependency>
  <!-- JavaMail RI -->
  <groupId>com.sun.mail</groupId>
  <artifactId>javax.mail</artifactId>
  <scope>runtime</scope>
</dependency>
<dependency>
  <!-- JavaMail API -->
  <groupId>javax.mail</groupId>
  <artifactId>javax.mail-api</artifactId>
  <scope>compile</scope>
  <!-- let it stay as a runtime scoped dependency
  <exclusions>
    <exclusion>
      <groupId>javax.activation</groupId>
      <artifactId>activation</artifactId>
    </exclusion>
  </exclusions>
  -->
</dependency>

dependency:tree

[INFO] +- com.sun.mail:javax.mail:jar:1.5.4:runtime
[INFO] |  \- (javax.activation:activation:jar:1.1:compile
              - scope updated from runtime; omitted for duplicate)
[INFO] +- javax.mail:javax.mail-api:jar:1.5.4:compile
[INFO] |  \- javax.activation:activation:jar:1.1:compile
[INFO] +- com.sun.mail:javax.mail:jar:1.5.4:runtime
[INFO] |  \- javax.activation:activation:jar:1.1:runtime
[INFO] +- javax.mail:javax.mail-api:jar:1.5.4:compile

나는 수학이 싫어요.


what the…?

  1. 당신의 휴대폰 번호 뒷 네자리에 2를 곱한다.
  2. 다시 다하기 5를 한다.
  3. 다시 곱하기 50을 한다.
  4. 다시 더하기 1766를 한다.
  5. 그리고 당신의 태어난 년도를 뺀다.
  6. 그러면 앞 네자리는 당신의 폰번호이고 뒷 두자리는 당신의 나이이다.

liberate me

(2p + 5)\times 50 + 1766 - y
100p + 250 + 1766 - 7
100p + 2016 - y

100p가 첫 네자리를 폰번호로 만들고 5 * 50 + 1766이 현재년도(2016)을 만드는 구냥!
2 5 50 1766를 각각 a b c d로 하면 다음 공식을 만족하는 자연수들이 모두 이용될 수 있지 않을깡?

a\times c = 100
b\times c + d = 2016

아몰랑, 안해!

wolfram alpha

다음의 해에서 c를 고른 다음,
solve a * c = 100 and a > 0 over the integers
다음의 query에 대입해서 보자.
solve b * c + d = 2016 and c = 2 and d > 0 over the integers

Pointers to arrays in C (translated)


이 문서는 Pointers to arrays in C (Eli Bendersky’s website)의 번역본입니다. 번역이 조금 이상하더라도 이해해주세요. ^^*. 하고나니 이상하네요.


포인터는 C 언어에서 혼란을 초래하는 큰 원인중 하나입니다. 초보자들을 힘들게 하죠. 하지만, array와 같이 엮기면, 숙달된 프로그래머들조차 복잡하게 느낍니다.

다음 코드를 한번 보죠.

void test(int** p)
{
}


int main()
{
    int arr[] = {30, 450, 14, 5};
    test(&arr);
    return 0;
}

잠시 곰곰히 생각해 보죠. 이 코드가 깔끔하게 컴파일될까요?

gcc는 그리 좋아하지 않는 것 같습니다. 다음과 같은 경고를 주네요. passing arg 1 of test from incompatible pointer type. C++은 좀더 엄격한 확인을 하니 g++로 한번 시도해 보겠습니다. 예상했듯이 에러를 냅니다. cannot convert int (*)[4] to int** for argument 1 to void test(int**).

뭐가 문제인걸까요? 위 코드에서 뭐가 잘못됬죠? 흠, 모든게요. 잘못되었기도 하거니와 이치에 맞지도 않습니다. 어떤 사람들은 잘 동작해야 한다고 생각합니다. 다음 코드가 잘 돌아가기 때문이죠.

void test(int* p) {
}

int main() {
  int arr[] = {30, 450, 14, 5};
  test(arr);
  return 0;
}

하지만 이 코드가 특별하게 동작하는 이유는 C 컴파일러가, 배열이 lvalue로 사용될 때는 포인터로 “변형(변질, decay)”된다, 라는 C 표준을 따르기 때문입니다. 즉 배열의 첫번째 요소를 가리키는 포인터가 test에 전달됨으로써 모든게 잘 동작합니다.

하지만 첫번째 코드는 다르죠. 배열의 이름은 포인터로 바뀌지만(decay) 배열 주소는 이중 포이터로 바뀌지(decay) 않습니다. 왜 그럴까요? 왜 배열은 그렇게 취급될까요?

이중포인터들(pointers to pointers)은 때로 포인터들의 값을 변경하기 위해 전달됩니다. (단일포인터들로는 그 포이터가 가르키는 값을 바꿀 수 있을 뿐 포인터 자체를 바꿀 수는 없죠.) 여기 가상의 코드가 있습니다. (컴파일 앙대요.)

void test(int** p)
{
    *p = malloc ... /* retarget '*p' */
}


int main()
{
    int arr[] = {30, 450, 14, 5};
    int* ptr;

    /* Fine!
    ** test will retarget ptr, and its new value
    ** will appear after this call.
    */
    test(&ptr);

    /* Makes no sense!
    ** You cannot retarget 'arr', since it's a
    ** constant label created by the compiler.
    */
    test(&arr);

    return 0;
}

Pointers to arrays

조금만 수정해서 동작하게 만들어 볼까요?

void test(int (*p)[4])
{
    (*p)[2] = 10;
}


int main()
{
    int arr[] = {30, 450, 14, 5};

    test(&arr);
    printf("%d\n", arr[2]);

    return 0;
}

test함수가 받는 요상한 건 뭔가요? C에서 가장 불필요한 것들 중 하나인 배열 포인터입니다. 여기 C FAQ의 답입니다.

2.12 배열의 포인터는 어떻게 선언하나요?
보통, 그렇게 할 경우가 없을텐데요. 사람들이 배열의 포인터를 얘기할 때는 배열의 첫번째 요소에 대한 포인터를 의미합니다.

맞네요. 실제로 배열의 포인터를 사용할 일이 없을 것 같습니다. 웹에서 검색을 해 보면, 대부분의 사람들이 foo(int* p)의 인자를 “배열을 가르키는 포인터”라고 잘못 알고 있습니다. 물론 아니죠. 모든 원인은 C의 선언문법의 유물이라고 생각합니다. (It looks to me like the whole concept is just an artifact of C’s declaration syntax.)

위의 test 함수는 컴파일도 되고 잘 동작하기도 하지만, 다음 코드가 훨씬 간단합니다.

void test(int* p)
{
    p[2] = 10;
}

...
...
/* then call */
test(arr);

함수의 인자로 전체 값을 넘기지 않기 위해 포인터를 주로 사용합니다. 혹은 포인터가 가르키는 값을 수정하기 위함이죠. 하기만 두 기능 모두 배열포인터와는 상관없습니다. 여기 그 증거가 있네요.

int joe[] = {1, 2, 3, 4};

void test(int (*p)[4])
{
    /* Fine: assign to an element through the
    ** pointer.
    */
    (*p)[2] = 10;

    /* Works, but won't be reflected in the
    ** caller since p was passed by value.
    */
    p = &joe;

    /* Error: arrays can't be assigned.
    */
    *p = joe;
}

배열이 값이 아닌 포인터로 전달되었지만 아무런 효과가 없습니다. 배열 자체도 수정될 수 없거니와 포인터가 가르키는 값도 수정할 수 없습니다.