View Javadoc
1   /*
2    * SPDX-FileCopyrightText: Copyright (c) 2012-2026 Yegor Bugayenko
3    * SPDX-License-Identifier: MIT
4    */
5   package com.jcabi.dynamo;
6   
7   import com.jcabi.immutable.ArrayMap;
8   import java.util.Collections;
9   import java.util.Random;
10  import java.util.UUID;
11  import org.hamcrest.MatcherAssert;
12  import org.hamcrest.Matchers;
13  import org.junit.jupiter.api.Assertions;
14  import org.junit.jupiter.api.Test;
15  import software.amazon.awssdk.services.dynamodb.model.AttributeValue;
16  import software.amazon.awssdk.services.dynamodb.model.ExpectedAttributeValue;
17  
18  /**
19   * Test case for {@link Attributes}.
20   * @since 0.1
21   */
22  @SuppressWarnings("PMD.TooManyMethods")
23  final class AttributesTest {
24  
25      @Test
26      void worksAsMapWithCorrectKeySetSize() {
27          MatcherAssert.assertThat(
28              "should has size 1",
29              new Attributes().with(
30                  "id",
31                  AttributeValue.builder().s("some text value").build()
32              ).keySet(),
33              Matchers.hasSize(1)
34          );
35      }
36  
37      @Test
38      void worksAsMapWithCorrectEntry() {
39          final String attr = "id";
40          final AttributeValue value = AttributeValue.builder().s("some text value").build();
41          MatcherAssert.assertThat(
42              "should has some entry",
43              new Attributes().with(attr, value),
44              Matchers.hasEntry(attr, value)
45          );
46      }
47  
48      @Test
49      void worksAsMapFromExistingMap() {
50          final String attr = "id";
51          final AttributeValue value = AttributeValue.builder().s("some text value").build();
52          MatcherAssert.assertThat(
53              "should has some text value",
54              new Attributes(new Attributes().with(attr, value)),
55              Matchers.hasEntry(attr, value)
56          );
57      }
58  
59      @Test
60      void buildsExpectedKeys() {
61          final String attr = "attr-13";
62          final String value = "some value \u20ac";
63          MatcherAssert.assertThat(
64              "should has 'some value \u20ac'",
65              new Attributes().with(attr, value).asKeys(),
66              Matchers.hasEntry(
67                  attr,
68                  ExpectedAttributeValue.builder().value(
69                      AttributeValue.builder().s(value).build()
70                  ).build()
71              )
72          );
73      }
74  
75      @Test
76      void filtersOutUnnecessaryKeys() {
77          MatcherAssert.assertThat(
78              "should be empty match",
79              new Attributes()
80                  .with("first", "test-1")
81                  .with("second", "test-2")
82                  .only(Collections.singletonList("never"))
83                  .keySet(),
84              Matchers.empty()
85          );
86      }
87  
88      @Test
89      void caseSensitiveWithDifferentCase() {
90          MatcherAssert.assertThat(
91              "should has size 2",
92              new Attributes().with(
93                  new ArrayMap<String, AttributeValue>()
94                      .with("Gamma", AttributeValue.builder().s("").build())
95                      .with("gAMma", AttributeValue.builder().s("").build())
96              ).keySet(),
97              Matchers.hasSize(2)
98          );
99      }
100 
101     @Test
102     void caseSensitivePreservesKeys() {
103         final String first = "Alpha";
104         final String second = "AlPha";
105         MatcherAssert.assertThat(
106             "should has keys 'Alpha', 'AlPha'",
107             new Attributes()
108                 .with(first, "val-1")
109                 .with(second, "val-2"),
110             Matchers.allOf(
111                 Matchers.hasKey(first),
112                 Matchers.hasKey(second)
113             )
114         );
115     }
116 
117     @Test
118     void caseSensitiveFiltersCorrectly() {
119         final String third = "Beta";
120         MatcherAssert.assertThat(
121             "should has key 'Beta'",
122             new Attributes()
123                 .with(third, "some text to use")
124                 .only(Collections.singletonList(third)),
125             Matchers.hasKey(third)
126         );
127     }
128 
129     @Test
130     void buildsWithLongValue() {
131         final String attr = UUID.randomUUID().toString();
132         final long number = new Random().nextLong();
133         MatcherAssert.assertThat(
134             "did not store long value as numeric attribute",
135             new Attributes().with(attr, number).get(attr).n(),
136             Matchers.equalTo(String.valueOf(number))
137         );
138     }
139 
140     @Test
141     void buildsWithIntegerValue() {
142         final String attr = UUID.randomUUID().toString();
143         final int number = new Random().nextInt();
144         MatcherAssert.assertThat(
145             "did not store integer value as numeric attribute",
146             new Attributes().with(attr, number).get(attr).n(),
147             Matchers.equalTo(String.valueOf(number))
148         );
149     }
150 
151     @Test
152     void rejectsDirectPut() {
153         Assertions.assertThrows(
154             UnsupportedOperationException.class,
155             () -> new Attributes().put(
156                 UUID.randomUUID().toString(),
157                 AttributeValue.builder().s("ü").build()
158             )
159         );
160     }
161 
162     @Test
163     void rejectsDirectRemove() {
164         Assertions.assertThrows(
165             UnsupportedOperationException.class,
166             () -> new Attributes().remove(UUID.randomUUID().toString())
167         );
168     }
169 
170     @Test
171     void rejectsDirectClear() {
172         Assertions.assertThrows(
173             UnsupportedOperationException.class,
174             () -> new Attributes().clear()
175         );
176     }
177 
178     @Test
179     void rejectsDirectPutAll() {
180         Assertions.assertThrows(
181             UnsupportedOperationException.class,
182             () -> new Attributes().putAll(
183                 Collections.singletonMap(
184                     UUID.randomUUID().toString(),
185                     AttributeValue.builder().s("ö").build()
186                 )
187             )
188         );
189     }
190 
191     @Test
192     void retainsOnlyMatchingKeys() {
193         final String kept = UUID.randomUUID().toString();
194         MatcherAssert.assertThat(
195             "did not retain the matching key",
196             new Attributes()
197                 .with(kept, "ütf-vàl")
198                 .with(UUID.randomUUID().toString(), "öther")
199                 .only(Collections.singletonList(kept)),
200             Matchers.hasKey(kept)
201         );
202     }
203 
204     @Test
205     void mergesWithMapOfAttributes() {
206         MatcherAssert.assertThat(
207             "did not merge all map entries",
208             new Attributes().with(
209                 new ArrayMap<String, AttributeValue>()
210                     .with(
211                         UUID.randomUUID().toString(),
212                         AttributeValue.builder().s("ä").build()
213                     )
214                     .with(
215                         UUID.randomUUID().toString(),
216                         AttributeValue.builder().s("ö").build()
217                     )
218             ).keySet(),
219             Matchers.hasSize(2)
220         );
221     }
222 
223     @Test
224     void convertsMultipleAttributesToExpectedKeys() {
225         MatcherAssert.assertThat(
226             "did not convert all attributes to expected keys",
227             new Attributes()
228                 .with(UUID.randomUUID().toString(), "vàl-1")
229                 .with(UUID.randomUUID().toString(), "vàl-2")
230                 .asKeys().keySet(),
231             Matchers.hasSize(2)
232         );
233     }
234 
235 }