blob: 6ba026fb83238fe6b2b70d2b2d282080d3107663 [file] [log] [blame]
Julien Desprez093c3f62018-05-21 16:23:37 -07001/*
2 * Copyright (C) 2018 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16package com.android.tradefed.result.proto;
17
Julien Desprez5035aa62019-07-27 17:11:57 -070018import com.android.tradefed.config.Option;
Julien Desprez093c3f62018-05-21 16:23:37 -070019import com.android.tradefed.config.OptionClass;
20import com.android.tradefed.invoker.IInvocationContext;
21import com.android.tradefed.log.LogUtil.CLog;
22import com.android.tradefed.metrics.proto.MetricMeasurement.Metric;
Julien Desprez8ee09232020-02-06 10:30:11 -080023import com.android.tradefed.result.FailureDescription;
Julien Desprez093c3f62018-05-21 16:23:37 -070024import com.android.tradefed.result.ILogSaverListener;
25import com.android.tradefed.result.ITestInvocationListener;
Julien Desprez093c3f62018-05-21 16:23:37 -070026import com.android.tradefed.result.LogFile;
27import com.android.tradefed.result.TestDescription;
Julien Desprezed8bd9b2018-07-13 08:50:20 -070028import com.android.tradefed.result.proto.LogFileProto.LogFileInfo;
29import com.android.tradefed.result.proto.TestRecordProto.ChildReference;
30import com.android.tradefed.result.proto.TestRecordProto.DebugInfo;
Julien Desprez221aaf12020-02-27 14:17:03 -080031import com.android.tradefed.result.proto.TestRecordProto.DebugInfoContext;
Julien Desprezed8bd9b2018-07-13 08:50:20 -070032import com.android.tradefed.result.proto.TestRecordProto.TestRecord;
33import com.android.tradefed.result.proto.TestRecordProto.TestStatus;
Julien Desprez5035aa62019-07-27 17:11:57 -070034import com.android.tradefed.result.retry.ISupportGranularResults;
Julien Desprez093c3f62018-05-21 16:23:37 -070035import com.android.tradefed.testtype.suite.ModuleDefinition;
Julien Desprezdbc1f172018-12-21 12:14:33 -080036import com.android.tradefed.util.StreamUtil;
Julien Desprez093c3f62018-05-21 16:23:37 -070037
Julien Desprez221aaf12020-02-27 14:17:03 -080038import com.google.common.base.Strings;
Julien Desprez093c3f62018-05-21 16:23:37 -070039import com.google.protobuf.Any;
40import com.google.protobuf.Timestamp;
Julien Desprez093c3f62018-05-21 16:23:37 -070041
42import java.util.HashMap;
43import java.util.Map;
44import java.util.Stack;
45import java.util.UUID;
46
47/**
48 * Result reporter build a {@link TestRecord} protobuf with all the results inside. Should be
49 * extended to handle what to do with the final proto in {@link #processFinalProto(TestRecord)}.
50 */
51@OptionClass(alias = "proto-reporter")
Julien Desprez5035aa62019-07-27 17:11:57 -070052public abstract class ProtoResultReporter
53 implements ITestInvocationListener, ILogSaverListener, ISupportGranularResults {
54
55 @Option(
56 name = "enable-granular-attempts",
57 description =
58 "Whether or not to allow this reporter receiving granular attempts. Feature flag."
59 )
60 private boolean mReportGranularResults = true;
Julien Desprez093c3f62018-05-21 16:23:37 -070061
62 private Stack<TestRecord.Builder> mLatestChild;
63 private TestRecord.Builder mInvocationRecordBuilder;
64 private long mInvocationStartTime;
Julien Desprezf066b702018-11-07 11:10:08 -080065 private IInvocationContext mContext;
Julien Desprez093c3f62018-05-21 16:23:37 -070066
Julien Desprezdbc1f172018-12-21 12:14:33 -080067 private Throwable mInvocationFailure = null;
Julien Desprez079ab2f2019-03-12 10:03:45 -070068 /** Whether or not a testModuleStart had currently been called. */
69 private boolean mModuleInProgress = false;
Julien Desprezdbc1f172018-12-21 12:14:33 -080070
Julien Desprez5035aa62019-07-27 17:11:57 -070071 @Override
72 public boolean supportGranularResults() {
73 return mReportGranularResults;
74 }
75
Julien Desprez093c3f62018-05-21 16:23:37 -070076 /**
77 * Handling of the partial invocation test record proto after {@link
78 * #invocationStarted(IInvocationContext)} occurred.
79 *
80 * @param invocationStartRecord The partial proto populated after the invocationStart.
Julien Desprez329294b2018-07-25 10:16:59 -070081 * @param invocationContext The invocation {@link IInvocationContext}.
Julien Desprez093c3f62018-05-21 16:23:37 -070082 */
Julien Desprez329294b2018-07-25 10:16:59 -070083 public void processStartInvocation(
84 TestRecord invocationStartRecord, IInvocationContext invocationContext) {}
Julien Desprez093c3f62018-05-21 16:23:37 -070085
86 /**
87 * Handling of the final proto with all results.
88 *
89 * @param finalRecord The finalized proto with all the invocation results.
90 */
91 public void processFinalProto(TestRecord finalRecord) {}
92
93 /**
94 * Handling of the partial module record proto after {@link
95 * #testModuleStarted(IInvocationContext)} occurred.
96 *
97 * @param moduleStartRecord The partial proto representing the module.
98 */
99 public void processTestModuleStarted(TestRecord moduleStartRecord) {}
100
101 /**
102 * Handling of the finalized module record proto after {@link #testModuleEnded()} occurred.
103 *
104 * @param moduleRecord The finalized proto representing the module.
105 */
106 public void processTestModuleEnd(TestRecord moduleRecord) {}
107
108 /**
109 * Handling of the partial test run record proto after {@link #testRunStarted(String, int)}
110 * occurred.
111 *
112 * @param runStartedRecord The partial proto representing the run.
113 */
114 public void processTestRunStarted(TestRecord runStartedRecord) {}
115
116 /**
117 * Handling of the finalized run record proto after {@link #testRunEnded(long, HashMap)}
118 * occurred.
119 *
120 * @param runRecord The finalized proto representing the run.
Julien Desprez1bece772019-05-20 12:15:11 -0700121 * @param moduleInProgress whether or not a module is in progress.
Julien Desprez093c3f62018-05-21 16:23:37 -0700122 */
Julien Desprez1bece772019-05-20 12:15:11 -0700123 public void processTestRunEnded(TestRecord runRecord, boolean moduleInProgress) {}
Julien Desprez093c3f62018-05-21 16:23:37 -0700124
125 /**
126 * Handling of the partial test case record proto after {@link #testStarted(TestDescription,
127 * long)} occurred.
128 *
129 * @param testCaseStartedRecord The partial proto representing the test case.
130 */
131 public void processTestCaseStarted(TestRecord testCaseStartedRecord) {}
132
133 /**
134 * Handling of the finalized test case record proto after {@link #testEnded(TestDescription,
135 * long, HashMap)} occurred.
136 *
137 * @param testCaseRecord The finalized proto representing a test case.
138 */
139 public void processTestCaseEnded(TestRecord testCaseRecord) {}
140
141 // Invocation events
142
143 @Override
144 public final void invocationStarted(IInvocationContext context) {
145 mLatestChild = new Stack<>();
146 mInvocationRecordBuilder = TestRecord.newBuilder();
147 // Set invocation unique id
148 mInvocationRecordBuilder.setTestRecordId(UUID.randomUUID().toString());
149
150 // Populate start time of invocation
151 mInvocationStartTime = System.currentTimeMillis();
152 Timestamp startTime = createTimeStamp(mInvocationStartTime);
153 mInvocationRecordBuilder.setStartTime(startTime);
Julien Desprez50706022018-07-18 15:41:44 -0700154 mInvocationRecordBuilder.setDescription(Any.pack(context.toProto()));
Julien Desprez093c3f62018-05-21 16:23:37 -0700155
Julien Desprezf066b702018-11-07 11:10:08 -0800156 mContext = context;
157
Julien Desprez093c3f62018-05-21 16:23:37 -0700158 // Put the invocation record at the bottom of the stack
159 mLatestChild.add(mInvocationRecordBuilder);
160
161 // Send the invocation proto with the currently set information to indicate the beginning
162 // of the invocation.
163 TestRecord startInvocationProto = mInvocationRecordBuilder.build();
164 try {
Julien Desprez329294b2018-07-25 10:16:59 -0700165 processStartInvocation(startInvocationProto, context);
Julien Desprez093c3f62018-05-21 16:23:37 -0700166 } catch (RuntimeException e) {
167 CLog.e("Failed to process invocation started:");
168 CLog.e(e);
169 }
170 }
171
172 @Override
Julien Desprezdbc1f172018-12-21 12:14:33 -0800173 public void invocationFailed(Throwable cause) {
174 mInvocationFailure = cause;
175 }
176
177 @Override
Julien Desprez093c3f62018-05-21 16:23:37 -0700178 public final void invocationEnded(long elapsedTime) {
Julien Desprez079ab2f2019-03-12 10:03:45 -0700179 if (mModuleInProgress) {
180 // If we had a module in progress, and a new module start occurs, complete the call
181 testModuleEnded();
182 }
Julien Desprez093c3f62018-05-21 16:23:37 -0700183 // Populate end time of invocation
184 Timestamp endTime = createTimeStamp(mInvocationStartTime + elapsedTime);
185 mInvocationRecordBuilder.setEndTime(endTime);
Julien Desprezf066b702018-11-07 11:10:08 -0800186 // Update the context in case it changed
187 mInvocationRecordBuilder.setDescription(Any.pack(mContext.toProto()));
Julien Desprez093c3f62018-05-21 16:23:37 -0700188
Julien Desprezdbc1f172018-12-21 12:14:33 -0800189 if (mInvocationFailure != null) {
190 DebugInfo.Builder debugBuilder = DebugInfo.newBuilder();
Julien Desprez14a2ceb2019-07-15 12:03:17 -0700191 if (mInvocationFailure.getMessage() != null) {
192 debugBuilder.setErrorMessage(mInvocationFailure.getMessage());
193 }
Julien Desprezdbc1f172018-12-21 12:14:33 -0800194 debugBuilder.setTrace(StreamUtil.getStackTrace(mInvocationFailure));
195 mInvocationRecordBuilder.setDebugInfo(debugBuilder);
196 }
197
Julien Desprez093c3f62018-05-21 16:23:37 -0700198 // Finalize the protobuf handling: where to put the results.
199 TestRecord record = mInvocationRecordBuilder.build();
200 try {
201 processFinalProto(record);
202 } catch (RuntimeException e) {
203 CLog.e("Failed to process invocation ended:");
204 CLog.e(e);
205 }
206 }
207
208 // Module events (optional when there is no suite)
209
210 @Override
211 public final void testModuleStarted(IInvocationContext moduleContext) {
Julien Desprez079ab2f2019-03-12 10:03:45 -0700212 if (mModuleInProgress) {
213 // If we had a module in progress, and a new module start occurs, complete the call
214 testModuleEnded();
215 }
Julien Desprez093c3f62018-05-21 16:23:37 -0700216 TestRecord.Builder moduleBuilder = TestRecord.newBuilder();
217 moduleBuilder.setParentTestRecordId(mInvocationRecordBuilder.getTestRecordId());
218 moduleBuilder.setTestRecordId(
219 moduleContext.getAttributes().get(ModuleDefinition.MODULE_ID).get(0));
220 moduleBuilder.setStartTime(createTimeStamp(System.currentTimeMillis()));
Julien Desprez50706022018-07-18 15:41:44 -0700221 moduleBuilder.setDescription(Any.pack(moduleContext.toProto()));
Julien Desprez093c3f62018-05-21 16:23:37 -0700222 mLatestChild.add(moduleBuilder);
Julien Desprez079ab2f2019-03-12 10:03:45 -0700223 mModuleInProgress = true;
Julien Desprez093c3f62018-05-21 16:23:37 -0700224 try {
225 processTestModuleStarted(moduleBuilder.build());
226 } catch (RuntimeException e) {
227 CLog.e("Failed to process invocation ended:");
228 CLog.e(e);
229 }
230 }
231
232 @Override
233 public final void testModuleEnded() {
234 TestRecord.Builder moduleBuilder = mLatestChild.pop();
Julien Desprez079ab2f2019-03-12 10:03:45 -0700235 mModuleInProgress = false;
Julien Desprez093c3f62018-05-21 16:23:37 -0700236 moduleBuilder.setEndTime(createTimeStamp(System.currentTimeMillis()));
237 TestRecord.Builder parentBuilder = mLatestChild.peek();
238
239 // Finalize the module and track it in the child
240 TestRecord moduleRecord = moduleBuilder.build();
241 parentBuilder.addChildren(createChildReference(moduleRecord));
242 try {
243 processTestModuleEnd(moduleRecord);
244 } catch (RuntimeException e) {
245 CLog.e("Failed to process test module end:");
246 CLog.e(e);
247 }
248 }
249
250 // Run events
251
252 @Override
253 public final void testRunStarted(String runName, int testCount) {
Julien Desprezb18ff872018-08-16 10:34:28 -0700254 testRunStarted(runName, testCount, 0);
255 }
256
257 @Override
258 public void testRunStarted(String runName, int testCount, int attemptNumber) {
Julien Desprezbd1f3762019-04-19 14:57:00 -0700259 testRunStarted(runName, testCount, attemptNumber, System.currentTimeMillis());
260 }
261
262 @Override
263 public void testRunStarted(String runName, int testCount, int attemptNumber, long startTime) {
Julien Desprez093c3f62018-05-21 16:23:37 -0700264 TestRecord.Builder runBuilder = TestRecord.newBuilder();
265 TestRecord.Builder parent = mLatestChild.peek();
266 runBuilder.setParentTestRecordId(parent.getTestRecordId());
267 runBuilder.setTestRecordId(runName);
268 runBuilder.setNumExpectedChildren(testCount);
Julien Desprezbd1f3762019-04-19 14:57:00 -0700269 runBuilder.setStartTime(createTimeStamp(startTime));
Julien Desprezb18ff872018-08-16 10:34:28 -0700270 runBuilder.setAttemptId(attemptNumber);
Julien Desprez093c3f62018-05-21 16:23:37 -0700271
272 mLatestChild.add(runBuilder);
273 try {
274 processTestRunStarted(runBuilder.build());
275 } catch (RuntimeException e) {
276 CLog.e("Failed to process invocation ended:");
277 CLog.e(e);
278 }
279 }
280
281 @Override
282 public final void testRunFailed(String errorMessage) {
283 TestRecord.Builder current = mLatestChild.peek();
284 DebugInfo.Builder debugBuilder = DebugInfo.newBuilder();
285 debugBuilder.setErrorMessage(errorMessage);
286 if (TestStatus.UNKNOWN.equals(current.getStatus())) {
287 current.setDebugInfo(debugBuilder.build());
288 } else {
289 // We are in a test case and we need the run parent.
290 TestRecord.Builder test = mLatestChild.pop();
291 TestRecord.Builder run = mLatestChild.peek();
292 run.setDebugInfo(debugBuilder.build());
293 // Re-add the test
294 mLatestChild.add(test);
295 }
296 }
297
298 @Override
Julien Desprez8ee09232020-02-06 10:30:11 -0800299 public final void testRunFailed(FailureDescription failure) {
300 TestRecord.Builder current = mLatestChild.peek();
301 DebugInfo.Builder debugBuilder = DebugInfo.newBuilder();
302 debugBuilder.setErrorMessage(failure.toString());
303 if (failure.getFailureStatus() != null) {
304 debugBuilder.setFailureStatus(failure.getFailureStatus());
305 }
Julien Desprez221aaf12020-02-27 14:17:03 -0800306 DebugInfoContext.Builder debugContext = DebugInfoContext.newBuilder();
307 if (failure.getActionInProgress() != null) {
308 debugContext.setActionInProgress(failure.getActionInProgress().toString());
309 }
310 if (!Strings.isNullOrEmpty(failure.getDebugHelpMessage())) {
311 debugContext.setDebugHelpMessage(failure.getDebugHelpMessage());
312 }
313 debugBuilder.setDebugInfoContext(debugContext.build());
314
Julien Desprez8ee09232020-02-06 10:30:11 -0800315 if (TestStatus.UNKNOWN.equals(current.getStatus())) {
316 current.setDebugInfo(debugBuilder.build());
317 } else {
318 // We are in a test case and we need the run parent.
319 TestRecord.Builder test = mLatestChild.pop();
320 TestRecord.Builder run = mLatestChild.peek();
321 run.setDebugInfo(debugBuilder.build());
322 // Re-add the test
323 mLatestChild.add(test);
324 }
325 }
326
327 @Override
Julien Desprez093c3f62018-05-21 16:23:37 -0700328 public final void testRunEnded(long elapsedTimeMillis, HashMap<String, Metric> runMetrics) {
329 TestRecord.Builder runBuilder = mLatestChild.pop();
Julien Desprezbd1f3762019-04-19 14:57:00 -0700330 long startTime = timeStampToMillis(runBuilder.getStartTime());
331 runBuilder.setEndTime(createTimeStamp(startTime + elapsedTimeMillis));
Julien Desprez093c3f62018-05-21 16:23:37 -0700332 runBuilder.putAllMetrics(runMetrics);
333 TestRecord.Builder parentBuilder = mLatestChild.peek();
334
335 // Finalize the run and track it in the child
336 TestRecord runRecord = runBuilder.build();
337 parentBuilder.addChildren(createChildReference(runRecord));
338 try {
Julien Desprez1bece772019-05-20 12:15:11 -0700339 processTestRunEnded(runRecord, mModuleInProgress);
Julien Desprez093c3f62018-05-21 16:23:37 -0700340 } catch (RuntimeException e) {
341 CLog.e("Failed to process test run end:");
342 CLog.e(e);
343 }
344 }
345
346 // test case events
347
348 @Override
Julien Desprez329294b2018-07-25 10:16:59 -0700349 public final void testStarted(TestDescription test) {
350 testStarted(test, System.currentTimeMillis());
351 }
352
353 @Override
Julien Desprez093c3f62018-05-21 16:23:37 -0700354 public final void testStarted(TestDescription test, long startTime) {
355 TestRecord.Builder testBuilder = TestRecord.newBuilder();
356 TestRecord.Builder parent = mLatestChild.peek();
357 testBuilder.setParentTestRecordId(parent.getTestRecordId());
358 testBuilder.setTestRecordId(test.toString());
359 testBuilder.setStartTime(createTimeStamp(startTime));
360 testBuilder.setStatus(TestStatus.PASS);
361
362 mLatestChild.add(testBuilder);
363 try {
364 processTestCaseStarted(testBuilder.build());
365 } catch (RuntimeException e) {
366 CLog.e("Failed to process invocation ended:");
367 CLog.e(e);
368 }
369 }
370
371 @Override
Julien Desprez329294b2018-07-25 10:16:59 -0700372 public void testEnded(TestDescription test, HashMap<String, Metric> testMetrics) {
373 testEnded(test, System.currentTimeMillis(), testMetrics);
374 }
375
376 @Override
Julien Desprez093c3f62018-05-21 16:23:37 -0700377 public final void testEnded(
378 TestDescription test, long endTime, HashMap<String, Metric> testMetrics) {
379 TestRecord.Builder testBuilder = mLatestChild.pop();
380 testBuilder.setEndTime(createTimeStamp(endTime));
381 testBuilder.putAllMetrics(testMetrics);
382 TestRecord.Builder parentBuilder = mLatestChild.peek();
383
384 // Finalize the run and track it in the child
385 TestRecord testCaseRecord = testBuilder.build();
386 parentBuilder.addChildren(createChildReference(testCaseRecord));
387 try {
388 processTestCaseEnded(testCaseRecord);
389 } catch (RuntimeException e) {
390 CLog.e("Failed to process test case end:");
391 CLog.e(e);
392 }
393 }
394
395 @Override
396 public final void testFailed(TestDescription test, String trace) {
397 TestRecord.Builder testBuilder = mLatestChild.peek();
398
399 testBuilder.setStatus(TestStatus.FAIL);
400 DebugInfo.Builder debugBuilder = DebugInfo.newBuilder();
401 // FIXME: extract the error message from the trace
402 debugBuilder.setErrorMessage(trace);
403 debugBuilder.setTrace(trace);
404 testBuilder.setDebugInfo(debugBuilder.build());
405 }
406
407 @Override
Julien Desprez8ee09232020-02-06 10:30:11 -0800408 public final void testFailed(TestDescription test, FailureDescription failure) {
409 TestRecord.Builder testBuilder = mLatestChild.peek();
410
411 testBuilder.setStatus(TestStatus.FAIL);
412 DebugInfo.Builder debugBuilder = DebugInfo.newBuilder();
413 // FIXME: extract the error message from the trace
414 debugBuilder.setErrorMessage(failure.toString());
415 debugBuilder.setTrace(failure.toString());
416 if (failure.getFailureStatus() != null) {
417 debugBuilder.setFailureStatus(failure.getFailureStatus());
418 }
Julien Desprez221aaf12020-02-27 14:17:03 -0800419 DebugInfoContext.Builder debugContext = DebugInfoContext.newBuilder();
420 if (failure.getActionInProgress() != null) {
421 debugContext.setActionInProgress(failure.getActionInProgress().toString());
422 }
423 if (!Strings.isNullOrEmpty(failure.getDebugHelpMessage())) {
424 debugContext.setDebugHelpMessage(failure.getDebugHelpMessage());
425 }
426 debugBuilder.setDebugInfoContext(debugContext.build());
427
Julien Desprez8ee09232020-02-06 10:30:11 -0800428 testBuilder.setDebugInfo(debugBuilder.build());
429 }
430
431 @Override
Julien Desprez093c3f62018-05-21 16:23:37 -0700432 public final void testIgnored(TestDescription test) {
433 TestRecord.Builder testBuilder = mLatestChild.peek();
434 testBuilder.setStatus(TestStatus.IGNORED);
435 }
436
437 @Override
438 public final void testAssumptionFailure(TestDescription test, String trace) {
439 TestRecord.Builder testBuilder = mLatestChild.peek();
440
441 testBuilder.setStatus(TestStatus.ASSUMPTION_FAILURE);
442 DebugInfo.Builder debugBuilder = DebugInfo.newBuilder();
443 // FIXME: extract the error message from the trace
444 debugBuilder.setErrorMessage(trace);
445 debugBuilder.setTrace(trace);
446 testBuilder.setDebugInfo(debugBuilder.build());
447 }
448
Julien Desprez53af5fe2020-02-19 10:31:38 -0800449 @Override
450 public final void testAssumptionFailure(TestDescription test, FailureDescription failure) {
451 TestRecord.Builder testBuilder = mLatestChild.peek();
452
453 testBuilder.setStatus(TestStatus.ASSUMPTION_FAILURE);
454 DebugInfo.Builder debugBuilder = DebugInfo.newBuilder();
455 // FIXME: extract the error message from the trace
456 debugBuilder.setErrorMessage(failure.toString());
457 debugBuilder.setTrace(failure.toString());
458 if (failure.getFailureStatus() != null) {
459 debugBuilder.setFailureStatus(failure.getFailureStatus());
460 }
461 testBuilder.setDebugInfo(debugBuilder.build());
462 }
463
Julien Desprez093c3f62018-05-21 16:23:37 -0700464 // log events
465
466 @Override
Julien Desprez093c3f62018-05-21 16:23:37 -0700467 public final void logAssociation(String dataName, LogFile logFile) {
468 TestRecord.Builder current = mLatestChild.peek();
469 Map<String, Any> fullmap = new HashMap<>();
Joseph Murphye87b17f2019-12-06 17:53:33 -0800470 fullmap.putAll(current.getArtifactsMap());
Julien Desprez093c3f62018-05-21 16:23:37 -0700471 Any any = Any.pack(createFileProto(logFile));
472 fullmap.put(dataName, any);
473 current.putAllArtifacts(fullmap);
474 }
475
476 private ChildReference createChildReference(TestRecord record) {
Julien Despreza49034d2018-07-24 10:07:10 -0700477 ChildReference.Builder child = ChildReference.newBuilder();
478 child.setTestRecordId(record.getTestRecordId());
479 child.setInlineTestRecord(record);
480 return child.build();
Julien Desprez093c3f62018-05-21 16:23:37 -0700481 }
482
483 /** Create and populate Timestamp as recommended in the javadoc of the Timestamp proto. */
484 private Timestamp createTimeStamp(long currentTimeMs) {
485 return Timestamp.newBuilder()
486 .setSeconds(currentTimeMs / 1000)
487 .setNanos((int) ((currentTimeMs % 1000) * 1000000))
488 .build();
489 }
490
Julien Desprezbd1f3762019-04-19 14:57:00 -0700491 private long timeStampToMillis(Timestamp stamp) {
492 return stamp.getSeconds() * 1000L + (stamp.getNanos() / 1000000L);
493 }
494
Julien Desprez093c3f62018-05-21 16:23:37 -0700495 private LogFileInfo createFileProto(LogFile logFile) {
496 LogFileInfo.Builder logFileBuilder = LogFileInfo.newBuilder();
497 logFileBuilder
498 .setPath(logFile.getPath())
Julien Desprez093c3f62018-05-21 16:23:37 -0700499 .setIsText(logFile.isText())
Julien Despreza49034d2018-07-24 10:07:10 -0700500 .setLogType(logFile.getType().toString())
Julien Desprez093c3f62018-05-21 16:23:37 -0700501 .setIsCompressed(logFile.isCompressed())
502 .setSize(logFile.getSize());
Julien Desprez329294b2018-07-25 10:16:59 -0700503 // Url can be null so avoid NPE by checking it before setting the proto
504 if (logFile.getUrl() != null) {
505 logFileBuilder.setUrl(logFile.getUrl());
506 }
Julien Desprez093c3f62018-05-21 16:23:37 -0700507 return logFileBuilder.build();
508 }
509}