embulk-executor-mapreduce 0.2.2 → 0.2.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (27) hide show
  1. checksums.yaml +4 -4
  2. data/classpath/{embulk-executor-mapreduce-0.2.2.jar → embulk-executor-mapreduce-0.2.3.jar} +0 -0
  3. data/src/main/java/org/embulk/executor/mapreduce/MapReduceExecutor.java +48 -24
  4. data/src/main/java/org/embulk/executor/mapreduce/TimestampPartitioning.java +11 -6
  5. data/src/test/java/org/embulk/executor/mapreduce/MapReduceExecutorTestRuntime.java +130 -0
  6. data/src/test/java/org/embulk/executor/mapreduce/TestAttemptState.java +58 -0
  7. data/src/test/java/org/embulk/executor/mapreduce/TestEmbulkInputFormat.java +54 -0
  8. data/src/test/java/org/embulk/executor/mapreduce/TestEmbulkInputSplit.java +46 -0
  9. data/src/test/java/org/embulk/executor/mapreduce/TestEmbulkRecordReader.java +25 -0
  10. data/src/test/java/org/embulk/executor/mapreduce/TestMapReduceExecutor.java +251 -0
  11. data/src/test/java/org/embulk/executor/mapreduce/TestPageBufferWritable.java +84 -0
  12. data/src/test/java/org/embulk/executor/mapreduce/TestTimestampPartitioning.java +222 -0
  13. data/src/test/resources/config/core-site.xml +8 -0
  14. data/src/test/resources/config/embulk_mapred_config.yml +38 -0
  15. data/src/test/resources/config/embulk_mapred_invalid_config_files_config.yml +38 -0
  16. data/src/test/resources/config/embulk_mapred_invalid_libjars_config.yml +40 -0
  17. data/src/test/resources/config/embulk_mapred_invalid_partitioning_config.yml +40 -0
  18. data/src/test/resources/config/embulk_mapred_invalid_reducers_config.yml +44 -0
  19. data/src/test/resources/config/embulk_mapred_partitioning_config.yml +43 -0
  20. data/src/test/resources/config/embulk_mapred_stop_on_invalid_record_config.yml +39 -0
  21. data/src/test/resources/config/hdfs-site.xml +18 -0
  22. data/src/test/resources/config/mapred-site.xml +8 -0
  23. data/src/test/resources/fixtures/csv/sample1.csv +3 -0
  24. data/src/test/resources/fixtures/csv/sample2.csv +4 -0
  25. data/src/test/resources/fixtures/invalid_csv/sample1.csv +4 -0
  26. data/src/test/resources/fixtures/invalid_csv/sample2.csv +3 -0
  27. metadata +25 -3
@@ -0,0 +1,25 @@
1
+ package org.embulk.executor.mapreduce;
2
+
3
+ import org.apache.hadoop.io.NullWritable;
4
+ import org.junit.Test;
5
+
6
+ import static org.junit.Assert.assertEquals;
7
+ import static org.junit.Assert.assertTrue;
8
+
9
+ public class TestEmbulkRecordReader
10
+ {
11
+ @Test
12
+ public void simpleTest()
13
+ {
14
+ int[] taskIndexes = new int[] {0, 1, 4, 6, 7};
15
+ try (EmbulkRecordReader r = new EmbulkRecordReader(new EmbulkInputSplit(taskIndexes))) {
16
+ int i = 0;
17
+ while (r.nextKeyValue()) {
18
+ assertEquals(taskIndexes[i], r.getCurrentKey().get());
19
+ assertTrue(r.getCurrentValue() instanceof NullWritable);
20
+ i++;
21
+ }
22
+ assertEquals(taskIndexes.length, i);
23
+ }
24
+ }
25
+ }
@@ -0,0 +1,251 @@
1
+ package org.embulk.executor.mapreduce;
2
+
3
+ import com.google.common.base.Function;
4
+ import com.google.common.collect.ImmutableList;
5
+ import com.google.common.collect.Iterables;
6
+ import com.google.inject.Binder;
7
+ import com.google.inject.Module;
8
+ import com.google.inject.Provider;
9
+ import com.google.inject.util.Modules;
10
+ import org.embulk.EmbulkEmbed;
11
+ import org.embulk.RandomManager;
12
+ import org.embulk.config.ConfigException;
13
+ import org.embulk.config.ConfigLoader;
14
+ import org.embulk.config.ConfigSource;
15
+ import org.embulk.config.UserDataExceptions;
16
+ import org.embulk.exec.PartialExecutionException;
17
+ import org.embulk.spi.ExecutorPlugin;
18
+ import org.junit.Before;
19
+ import org.junit.Test;
20
+ import org.slf4j.ILoggerFactory;
21
+ import org.slf4j.impl.Log4jLoggerFactory;
22
+
23
+ import java.io.FileNotFoundException;
24
+ import java.io.IOException;
25
+ import java.util.List;
26
+ import java.util.Random;
27
+
28
+ import static org.embulk.plugin.InjectedPluginSource.registerPluginTo;
29
+ import static org.junit.Assert.assertTrue;
30
+ import static org.junit.Assert.fail;
31
+
32
+ // this tests use Hadoop's standalone mode
33
+ public class TestMapReduceExecutor
34
+ {
35
+ private EmbulkEmbed embulk;
36
+ private Random random = new RandomManager(System.currentTimeMillis()).getRandom();
37
+
38
+ @Before
39
+ public void createResources()
40
+ {
41
+ EmbulkEmbed.Bootstrap bootstrap = new EmbulkEmbed.Bootstrap();
42
+
43
+ ConfigSource systemConfig = bootstrap.getSystemConfigLoader().newConfigSource();
44
+
45
+ if (random.nextBoolean()) {
46
+ systemConfig.set("embulk_factory_class", MapReduceEmbulkFactory.class.getName());
47
+ } else {
48
+ systemConfig.set("embulk_factory_class", MapReduceEmbulkFactory2.class.getName());
49
+ }
50
+
51
+ bootstrap.setSystemConfig(systemConfig);
52
+ bootstrap.overrideModules(getModuleOverrides(systemConfig));
53
+ embulk = bootstrap.initialize();
54
+ }
55
+
56
+ @Test
57
+ public void testEmbulkMapper()
58
+ throws Exception
59
+ {
60
+ ConfigSource config = loadConfigSource(embulk.newConfigLoader(), "config/embulk_mapred_config.yml");
61
+ embulk.run(config);
62
+ // TODO compare input and output
63
+ }
64
+
65
+ @Test
66
+ public void testEmbulkPartitioningMapperReducer()
67
+ throws Exception
68
+ {
69
+ ConfigSource config = loadConfigSource(embulk.newConfigLoader(), "config/embulk_mapred_partitioning_config.yml");
70
+ embulk.run(config);
71
+ // TODO compare input and output
72
+ }
73
+
74
+ @Test
75
+ public void testInvalidConfigFiles()
76
+ throws Exception
77
+ {
78
+ try {
79
+ ConfigSource config = loadConfigSource(embulk.newConfigLoader(), "config/embulk_mapred_invalid_config_files_config.yml");
80
+ embulk.run(config);
81
+ fail();
82
+ }
83
+ catch (Throwable t) {
84
+ assertTrue(t instanceof ConfigException);
85
+ }
86
+ }
87
+
88
+ @Test
89
+ public void testInvalidPartitioning()
90
+ throws Exception
91
+ {
92
+ try {
93
+ ConfigSource config = loadConfigSource(embulk.newConfigLoader(), "config/embulk_mapred_invalid_partitioning_config.yml");
94
+ embulk.run(config);
95
+ fail();
96
+ }
97
+ catch (Throwable t) {
98
+ assertTrue(t instanceof ConfigException);
99
+ }
100
+ }
101
+
102
+ @Test
103
+ public void testInvalidReducers()
104
+ throws Exception
105
+ {
106
+ try {
107
+ ConfigSource config = loadConfigSource(embulk.newConfigLoader(), "config/embulk_mapred_invalid_reducers_config.yml");
108
+ embulk.run(config);
109
+ fail();
110
+ }
111
+ catch (Throwable t) {
112
+ assertTrue(t instanceof ConfigException);
113
+ }
114
+ }
115
+
116
+ @Test
117
+ public void testInvalidLibjars()
118
+ throws Exception
119
+ {
120
+ try {
121
+ ConfigSource config = loadConfigSource(embulk.newConfigLoader(), "config/embulk_mapred_invalid_libjars_config.yml");
122
+ embulk.run(config);
123
+ fail();
124
+ }
125
+ catch (Throwable t) {
126
+ assertTrue(t.getCause() instanceof FileNotFoundException);
127
+ }
128
+ }
129
+
130
+ @Test
131
+ public void testStopOnInvalidRecord()
132
+ throws Exception
133
+ {
134
+ try {
135
+ ConfigSource config = loadConfigSource(embulk.newConfigLoader(), "config/embulk_mapred_stop_on_invalid_record_config.yml");
136
+ embulk.run(config);
137
+ fail();
138
+ }
139
+ catch (Throwable t) {
140
+ t.printStackTrace();
141
+ assertTrue(t instanceof PartialExecutionException);
142
+ assertTrue(UserDataExceptions.isUserDataException(t.getCause()));
143
+ }
144
+ }
145
+
146
+ private static ConfigSource loadConfigSource(ConfigLoader configLoader, String yamlFile)
147
+ throws IOException
148
+ {
149
+ return configLoader.fromYaml(TestMapReduceExecutor.class.getClassLoader().getResourceAsStream(yamlFile));
150
+ }
151
+
152
+ private static Function<List<Module>, List<Module>> getModuleOverrides(final ConfigSource systemConfig)
153
+ {
154
+ return new Function<List<Module>, List<Module>>()
155
+ {
156
+ public List<Module> apply(List<Module> modules)
157
+ {
158
+ return overrideModules(modules, systemConfig);
159
+ }
160
+ };
161
+ }
162
+
163
+ private static List<Module> overrideModules(List<Module> modules, ConfigSource systemConfig)
164
+ {
165
+ return ImmutableList.of(Modules.override(Iterables.concat(modules, getAdditionalModules(systemConfig)))
166
+ .with(getOverrideModules(systemConfig)));
167
+ }
168
+
169
+ private static List<Module> getAdditionalModules(ConfigSource systemConfig)
170
+ {
171
+ return ImmutableList.<Module>of(new ExecutorPluginApplyModule());
172
+ }
173
+
174
+ private static List<Module> getOverrideModules(ConfigSource systemConfig)
175
+ {
176
+ return ImmutableList.<Module>of(new LoggerOverrideModule());
177
+ }
178
+
179
+ static class ExecutorPluginApplyModule
180
+ implements Module
181
+ {
182
+ @Override
183
+ public void configure(Binder binder)
184
+ {
185
+ registerPluginTo(binder, ExecutorPlugin.class, "mapreduce", MapReduceExecutor.class);
186
+ }
187
+ }
188
+
189
+ static class LoggerOverrideModule
190
+ implements Module
191
+ {
192
+ @Override
193
+ public void configure(Binder binder)
194
+ {
195
+ binder.bind(ILoggerFactory.class).toProvider(new Provider<ILoggerFactory>()
196
+ {
197
+ @Override
198
+ public ILoggerFactory get()
199
+ {
200
+ return new Log4jLoggerFactory(); // YARN has used log4j.
201
+ }
202
+ });
203
+ }
204
+ }
205
+
206
+ public static class MapReduceEmbulkFactory
207
+ {
208
+ public EmbulkEmbed.Bootstrap bootstrap(final ConfigSource systemConfig)
209
+ {
210
+ EmbulkEmbed.Bootstrap bootstrap = new EmbulkEmbed.Bootstrap();
211
+ bootstrap.setSystemConfig(systemConfig);
212
+
213
+ // add modules
214
+ //bootstrap.addModules(ImmutableList.<Module>of());
215
+
216
+ // override modules
217
+ bootstrap.overrideModules(new Function<List<Module>, List<Module>>()
218
+ {
219
+ public List<Module> apply(List<Module> modules)
220
+ {
221
+ return ImmutableList.of(Modules.override(modules).with(new LoggerOverrideModule()));
222
+ }
223
+ });
224
+
225
+ return bootstrap;
226
+ }
227
+ }
228
+
229
+ public static class MapReduceEmbulkFactory2
230
+ {
231
+ public EmbulkEmbed.Bootstrap bootstrap(final ConfigSource systemConfig, final ConfigSource executorParams)
232
+ {
233
+ EmbulkEmbed.Bootstrap bootstrap = new EmbulkEmbed.Bootstrap();
234
+ bootstrap.setSystemConfig(systemConfig);
235
+
236
+ // add modules
237
+ //bootstrap.addModules(ImmutableList.<Module>of());
238
+
239
+ // override modules
240
+ bootstrap.overrideModules(new Function<List<Module>, List<Module>>()
241
+ {
242
+ public List<Module> apply(List<Module> modules)
243
+ {
244
+ return ImmutableList.of(Modules.override(modules).with(new LoggerOverrideModule()));
245
+ }
246
+ });
247
+
248
+ return bootstrap;
249
+ }
250
+ }
251
+ }
@@ -0,0 +1,84 @@
1
+ package org.embulk.executor.mapreduce;
2
+
3
+ import org.embulk.spi.Buffer;
4
+ import org.embulk.spi.Page;
5
+ import org.embulk.spi.PageTestUtils;
6
+ import org.embulk.spi.Schema;
7
+ import org.embulk.spi.time.Timestamp;
8
+ import org.embulk.spi.type.Types;
9
+ import org.junit.Rule;
10
+ import org.junit.Test;
11
+
12
+ import java.io.ByteArrayInputStream;
13
+ import java.io.ByteArrayOutputStream;
14
+ import java.io.DataInputStream;
15
+ import java.io.DataOutputStream;
16
+ import java.io.IOException;
17
+
18
+ import static org.junit.Assert.assertEquals;
19
+
20
+ public class TestPageBufferWritable
21
+ {
22
+ @Rule
23
+ public MapReduceExecutorTestRuntime runtime = new MapReduceExecutorTestRuntime();
24
+
25
+ @Test
26
+ public void writeAndRead() throws IOException
27
+ {
28
+ Schema schema = Schema.builder()
29
+ .add("c0", Types.BOOLEAN)
30
+ .add("c1", Types.LONG)
31
+ .add("c2", Types.DOUBLE)
32
+ .add("c3", Types.STRING)
33
+ .add("c4", Types.TIMESTAMP)
34
+ .build();
35
+
36
+ for (Page page : PageTestUtils.buildPage(runtime.getBufferAllocator(), schema,
37
+ true, 2L, 3.0D, "45", Timestamp.ofEpochMilli(678L),
38
+ true, 2L, 3.0D, "45", Timestamp.ofEpochMilli(678L))) {
39
+
40
+ try (ByteArrayOutputStream out = new ByteArrayOutputStream()) {
41
+ try (DataOutputStream dout = new DataOutputStream(out)) {
42
+ PageWritable pw1 = new PageWritable();
43
+ pw1.set(page);
44
+ pw1.write(dout);
45
+
46
+ BufferWritable bw1 = new BufferWritable();
47
+ bw1.set(page.buffer());
48
+ bw1.write(dout);
49
+ dout.flush();
50
+
51
+ try (DataInputStream din = new DataInputStream(new ByteArrayInputStream(out.toByteArray()))) {
52
+ PageWritable pw2 = new PageWritable();
53
+ pw2.readFields(din);
54
+
55
+ BufferWritable bw2 = new BufferWritable();
56
+ bw2.readFields(din);
57
+
58
+ assertPageWritableEquals(pw1, pw2);
59
+ assertBufferWritableEquals(bw1, bw2);
60
+ }
61
+ }
62
+ }
63
+ }
64
+ }
65
+
66
+ static void assertPageWritableEquals(PageWritable pw1, PageWritable pw2)
67
+ {
68
+ Page p1 = pw1.get();
69
+ Page p2 = pw2.get();
70
+
71
+ assertEquals(p1.getStringReferences(), p2.getStringReferences());
72
+ assertBufferEquals(p1.buffer(), p2.buffer());
73
+ }
74
+
75
+ static void assertBufferWritableEquals(BufferWritable bw1, BufferWritable bw2)
76
+ {
77
+ assertBufferEquals(bw1.get(), bw2.get());
78
+ }
79
+
80
+ static void assertBufferEquals(Buffer b1, Buffer b2)
81
+ {
82
+ assertEquals(b1, b2);
83
+ }
84
+ }
@@ -0,0 +1,222 @@
1
+ package org.embulk.executor.mapreduce;
2
+
3
+ import org.embulk.config.ConfigException;
4
+ import org.embulk.config.ConfigSource;
5
+ import org.embulk.spi.Column;
6
+ import org.embulk.spi.Page;
7
+ import org.embulk.spi.PageReader;
8
+ import org.embulk.spi.PageTestUtils;
9
+ import org.embulk.spi.Schema;
10
+ import org.embulk.spi.time.Timestamp;
11
+ import org.embulk.spi.type.Types;
12
+ import org.embulk.executor.mapreduce.TimestampPartitioning.LongUnixTimestampPartitioner;
13
+ import org.embulk.executor.mapreduce.TimestampPartitioning.TimestampPartitioner;
14
+ import org.embulk.executor.mapreduce.TimestampPartitioning.Unit;
15
+ import org.embulk.executor.mapreduce.TimestampPartitioning.UnixTimestampUnit;
16
+ import org.junit.Before;
17
+ import org.junit.Rule;
18
+ import org.junit.Test;
19
+
20
+ import java.io.IOException;
21
+ import java.util.ArrayList;
22
+ import java.util.Arrays;
23
+ import java.util.List;
24
+
25
+ import static org.junit.Assert.*;
26
+
27
+ public class TestTimestampPartitioning
28
+ {
29
+ @Rule
30
+ public MapReduceExecutorTestRuntime runtime = new MapReduceExecutorTestRuntime();
31
+
32
+ private TimestampPartitioning tp;
33
+
34
+ @Before
35
+ public void createTimestampPartitioning()
36
+ {
37
+ tp = new TimestampPartitioning();
38
+ }
39
+
40
+ @Test
41
+ public void validateConfigSource()
42
+ throws IOException
43
+ {
44
+ { // specified column is not included in schema
45
+ ConfigSource config = runtime.getExec().newConfigSource()
46
+ .set("column", "_c0").set("unit", "hour").set("timezone", "UTC");
47
+ Schema schema = Schema.builder().add("not_included", Types.TIMESTAMP).build();
48
+
49
+ try {
50
+ tp.configure(config, schema, 0);
51
+ fail();
52
+ } catch (Throwable t) {
53
+ assertTrue(t instanceof ConfigException);
54
+ }
55
+ }
56
+
57
+ { // only UTC is supported now
58
+ ConfigSource config = runtime.getExec().newConfigSource()
59
+ .set("column", "_c0").set("unit", "hour").set("timezone", "PDT");
60
+ Schema schema = Schema.builder().add("_c0", Types.TIMESTAMP).build();
61
+
62
+ try {
63
+ tp.configure(config, schema, 0);
64
+ fail();
65
+ } catch (Throwable t) {
66
+ assertTrue(t instanceof ConfigException);
67
+ }
68
+ }
69
+
70
+ { // the unit is only 'hour' or 'day'
71
+ ConfigSource config = runtime.getExec().newConfigSource()
72
+ .set("column", "_c0").set("unit", "invalid").set("timezone", "UTC");
73
+ Schema schema = Schema.builder().add("_c0", Types.TIMESTAMP).build();
74
+
75
+ try {
76
+ tp.configure(config, schema, 0);
77
+ fail();
78
+ } catch (Throwable t) {
79
+ assertTrue(t instanceof ConfigException);
80
+ }
81
+ }
82
+
83
+ { // the column type is only timestamp or long
84
+ ConfigSource config = runtime.getExec().newConfigSource()
85
+ .set("column", "_c0").set("unit", "hour").set("timezone", "UTC");
86
+ Schema schema = Schema.builder().add("_c0", Types.STRING).build();
87
+
88
+ try {
89
+ tp.configure(config, schema, 0);
90
+ fail();
91
+ } catch (Throwable t) {
92
+ assertTrue(t instanceof ConfigException);
93
+ }
94
+ }
95
+
96
+ { // if the column type is long, unix_timestamp_unit is required
97
+ ConfigSource config = runtime.getExec().newConfigSource()
98
+ .set("column", "_c0").set("unit", "hour").set("timezone", "UTC").set("unix_timestamp_unit", "invalid");
99
+ Schema schema = Schema.builder().add("_c0", Types.LONG).build();
100
+
101
+ try {
102
+ tp.configure(config, schema, 0);
103
+ fail();
104
+ } catch (Throwable t) {
105
+ assertTrue(t instanceof ConfigException);
106
+ }
107
+ }
108
+ }
109
+
110
+ @Test
111
+ public void comparePartitionKeys()
112
+ throws Exception
113
+ {
114
+ List<PartitionKey> pks = new ArrayList<>();
115
+
116
+ Column c0 = new Column(0, "c0", Types.LONG);
117
+ Column c1 = new Column(1, "c1", Types.TIMESTAMP);
118
+ Schema schema = new Schema(Arrays.asList(c0, c1));
119
+
120
+ LongUnixTimestampPartitioner lp = new LongUnixTimestampPartitioner(c0, Unit.HOUR, UnixTimestampUnit.SEC);
121
+ TimestampPartitioner tp = new TimestampPartitioner(c1, Unit.HOUR);
122
+
123
+ long timeWindow = System.currentTimeMillis()/1000/3600*3600;
124
+ PageReader r = new PageReader(schema);
125
+ for (Page page : PageTestUtils.buildPage(runtime.getBufferAllocator(), schema,
126
+ timeWindow, Timestamp.ofEpochSecond(timeWindow),
127
+ timeWindow+1, Timestamp.ofEpochSecond(timeWindow+1),
128
+ timeWindow+3600, Timestamp.ofEpochSecond(timeWindow+3600),
129
+ timeWindow+3600+1, Timestamp.ofEpochSecond(timeWindow+3600+1),
130
+ timeWindow+2*3600, Timestamp.ofEpochSecond(timeWindow+2*3600),
131
+ timeWindow+2*3600+1, Timestamp.ofEpochSecond(timeWindow+2*3600+1)
132
+ )){
133
+ r.setPage(page);
134
+ while (r.nextRecord()) {
135
+ pks.add(lp.updateKey(r).clone());
136
+ pks.add(tp.updateKey(r).clone());
137
+ }
138
+ }
139
+
140
+ for (int i = 0; i < pks.size(); i += 2) {
141
+ assertTrue(pks.get(i).equals(pks.get(i+1))); // long(tw) == timestamp(tw)
142
+ }
143
+ for (int i = 0; i < pks.size() - 4; i += 4) {
144
+ assertTrue(pks.get(i).equals(pks.get(i+2))); // long(tw) == long (tw+1)
145
+ }
146
+ for (int i = 0; i < pks.size() - 4; i += 4) {
147
+ assertFalse(pks.get(i).equals(pks.get(i+4))); // long(tw) != long (tw+3600)
148
+ }
149
+ }
150
+
151
+ @Test
152
+ public void checkUnit()
153
+ {
154
+ long hourlyTimeWindow = System.currentTimeMillis() / 1000 / 3600 * 3600;
155
+ long dailyTimeWindow = System.currentTimeMillis() / 1000 / 86400 * 86600;
156
+
157
+ // hour
158
+ {
159
+ assertEquals(Unit.HOUR, Unit.of("hour"));
160
+ assertTrue(Unit.HOUR.utcPartition(hourlyTimeWindow) == Unit.HOUR.utcPartition(hourlyTimeWindow + 1));
161
+ assertTrue(Unit.HOUR.utcPartition(hourlyTimeWindow) != Unit.HOUR.utcPartition(hourlyTimeWindow + 3600));
162
+ }
163
+
164
+ // day
165
+ {
166
+ assertEquals(Unit.DAY, Unit.of("day"));
167
+ assertTrue(Unit.DAY.utcPartition(dailyTimeWindow) == Unit.DAY.utcPartition(dailyTimeWindow + 1));
168
+ assertTrue(Unit.DAY.utcPartition(dailyTimeWindow) != Unit.DAY.utcPartition(dailyTimeWindow + 86400));
169
+ }
170
+
171
+ // invalid_unit
172
+ {
173
+ try {
174
+ Unit.of("invalid_unit");
175
+ fail();
176
+ } catch (Exception e) {
177
+ assertTrue(e instanceof ConfigException);
178
+ }
179
+ }
180
+ }
181
+
182
+ @Test
183
+ public void checkUnixTimestampUnit()
184
+ {
185
+ long currentNano = System.nanoTime();
186
+ long currentSec = currentNano / 1000000000;
187
+
188
+ // sec
189
+ {
190
+ assertEquals(UnixTimestampUnit.SEC, UnixTimestampUnit.of("sec"));
191
+ assertEquals(currentSec, UnixTimestampUnit.SEC.toSeconds(currentNano / 1000000000));
192
+ }
193
+
194
+ // milli
195
+ {
196
+ assertEquals(UnixTimestampUnit.MILLI, UnixTimestampUnit.of("milli"));
197
+ assertEquals(currentSec, UnixTimestampUnit.MILLI.toSeconds(currentNano / 1000000));
198
+ }
199
+
200
+ // micro
201
+ {
202
+ assertEquals(UnixTimestampUnit.MICRO, UnixTimestampUnit.of("micro"));
203
+ assertEquals(currentSec, UnixTimestampUnit.MICRO.toSeconds(currentNano / 1000));
204
+ }
205
+
206
+ // nano
207
+ {
208
+ assertEquals(UnixTimestampUnit.NANO, UnixTimestampUnit.of("nano"));
209
+ assertEquals(currentSec, UnixTimestampUnit.NANO.toSeconds(currentNano));
210
+ }
211
+
212
+ // invalid_unit
213
+ {
214
+ try {
215
+ UnixTimestampUnit.of("invalid_unit");
216
+ fail();
217
+ } catch (Exception e) {
218
+ assertTrue(e instanceof ConfigException);
219
+ }
220
+ }
221
+ }
222
+ }