View Javadoc
1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one or more
3    * contributor license agreements.  See the NOTICE file distributed with
4    * this work for additional information regarding copyright ownership.
5    * The ASF licenses this file to You under the Apache License, Version 2.0
6    * (the "License"); you may not use this file except in compliance with
7    * the License.  You may obtain a copy of the License at
8    *
9    *      http://www.apache.org/licenses/LICENSE-2.0
10   *
11   * Unless required by applicable law or agreed to in writing, software
12   * distributed under the License is distributed on an "AS IS" BASIS,
13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14   * See the License for the specific language governing permissions and
15   * limitations under the License.
16   */
17  
18  package org.apache.commons.collections4.map;
19  
20  import java.util.Objects;
21  
22  import org.junit.jupiter.api.Assertions;
23  import org.junit.jupiter.api.Test;
24  
25  /**
26   * Tests COMPRESS-872
27   * <p>
28   * Claim:
29   * </p>
30   * <ol>
31   * <li>Create a MultiKeyMap, with key(s) of a type (class/record) which has some fields.
32   * <li>Use multiKeyMap.put(T... keys, V value), to create an entry in the Map, to map the keys to a value
33   * <li>Use multiKeyMap.get(T... keys), to verify that the mapping exists and returns the expected value.
34   * <li>Modify/alter any of the objects used as a key. It is enough to change the value of any member field of any of the objects.
35   * <li>Use multiKeyMap.get(T... keys) again, however, now there is no mapping for these keys!
36   * <li>Use multiKeyMap.get(T... keys) with the new modified/altered objects, and it will return the expected value
37   * </ol>
38   * COUNTER CLAIM: The class is documented to use MultiKey which documents key elements as "The keys should be immutable".
39   */
40  public class MultiKeyMapCompress672Test {
41  
42      private static final class KeyFixture {
43  
44          private String value = "originalValue";
45  
46          @Override
47          public boolean equals(final Object obj) {
48              if (obj == null) {
49                  return false;
50              }
51              if (obj.getClass() != this.getClass()) {
52                  return false;
53              }
54              if (this == obj) {
55                  return true;
56              }
57              final KeyFixture object = (KeyFixture) obj;
58              if (getValue() == null) {
59                  return object.getValue() == null;
60              }
61              return getValue().equals(object.getValue());
62          }
63  
64          public String getValue() {
65              return value;
66          }
67  
68          @Override
69          public int hashCode() {
70              return Objects.hashCode(value);
71          }
72  
73          public void setValue(final String field) {
74              this.value = field;
75          }
76      }
77  
78      private static final String KEY_1 = "key1";
79  
80      private final MultiKeyMap<Object, String> multiKeyMap = new MultiKeyMap<>();
81  
82      @Test
83      public void testMutateKey() {
84          // Both objects have the 'field' value set to "originalValue"
85          final KeyFixture keyFixture2Ro = new KeyFixture();
86          final KeyFixture keyFixture2Rw = new KeyFixture();
87          // Put original mapping
88          Assertions.assertNull(multiKeyMap.put(KEY_1, keyFixture2Rw, "value"));
89          // Both mappings are correct
90          Assertions.assertEquals("value", multiKeyMap.get(KEY_1, keyFixture2Rw));
91          Assertions.assertEquals("value", multiKeyMap.get(KEY_1, keyFixture2Ro));
92          // Modify 'fixture2'
93          keyFixture2Rw.setValue("newValue");
94          // Modified mapping SHOULD NOT work
95          Assertions.assertNull(multiKeyMap.get(KEY_1, keyFixture2Rw));
96          // Claim: Original mapping SHOULD work
97          // COUNTER CLAIM: The class is documented to use MultiKey which documents key elements as "The keys should be immutable".
98          Assertions.assertNotEquals("value", multiKeyMap.get(KEY_1, keyFixture2Ro));
99      }
100 }