1 /*
   2  * Copyright (c) 2018, 2019, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.  Oracle designates this
   8  * particular file as subject to the "Classpath" exception as provided
   9  * by Oracle in the LICENSE file that accompanied this code.
  10  *
  11  * This code is distributed in the hope that it will be useful, but WITHOUT
  12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  14  * version 2 for more details (a copy is included in the LICENSE file that
  15  * accompanied this code).
  16  *
  17  * You should have received a copy of the GNU General Public License version
  18  * 2 along with this work; if not, write to the Free Software Foundation,
  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any
  23  * questions.
  24  */
  25 
  26 package jdk.jfr.api.recording.event;
  27 
  28 import java.time.Instant;
  29 import java.util.ArrayList;
  30 import java.util.Collections;
  31 import java.util.List;
  32 
  33 import jdk.jfr.Event;
  34 import jdk.jfr.Recording;
  35 import jdk.jfr.consumer.RecordedEvent;
  36 import jdk.testlibrary.Asserts;
  37 import jdk.testlibrary.jfr.CommonHelper;
  38 import jdk.testlibrary.jfr.EventNames;
  39 import jdk.testlibrary.jfr.Events;
  40 
  41 /*
  42  * @test
  43  * @summary Test getStartTime() and getEndTime(). Verify startTime <= endTime
  44  * @key jfr
  45  * @library /lib/testlibrary
  46  * @run main/othervm jdk.jfr.api.recording.event.TestEventTime
  47  */
  48 public class TestEventTime {
  49 
  50     static List<TimeEvent> actualOrder = new ArrayList<>();
  51 
  52     public static void main(String[] args) throws Throwable {
  53         Recording r = new Recording();
  54         r.enable(MyEvent.class).withoutStackTrace();
  55         // for debugging time related issues
  56         r.enable(EventNames.CPUTimeStampCounter);
  57         r.start();
  58         MyEvent event1 = beginEvent(1);
  59         MyEvent event2 = beginEvent(2);
  60         endEvent(event1);
  61         MyEvent event3 = beginEvent(3);
  62         endEvent(event2);
  63         endEvent(event3);
  64 
  65         r.stop();
  66 
  67         List<RecordedEvent> events = Events.fromRecording(r);
  68 
  69         RecordedEvent recEvent1 = findEvent(1, events);
  70         RecordedEvent recEvent2 = findEvent(2, events);
  71         RecordedEvent recEvent3 = findEvent(3, events);
  72 
  73         List<TimeEvent> recordedOrder = new ArrayList<>();
  74         recordedOrder.add(new TimeEvent(1, true, recEvent1.getStartTime()));
  75         recordedOrder.add(new TimeEvent(1, false, recEvent1.getEndTime()));
  76         recordedOrder.add(new TimeEvent(2, true, recEvent2.getStartTime()));
  77         recordedOrder.add(new TimeEvent(2, false, recEvent2.getEndTime()));
  78         recordedOrder.add(new TimeEvent(3, true, recEvent3.getStartTime()));
  79         recordedOrder.add(new TimeEvent(3, false, recEvent3.getEndTime()));
  80         Collections.sort(recordedOrder);
  81 
  82         printTimedEvents("Actual order", actualOrder);
  83         printTimedEvents("Recorded order", recordedOrder);
  84 
  85         for (int i = 0; i < 6; i++) {
  86             if (!actualOrder.get(i).equals(recordedOrder.get(i))) {
  87                 throw new Exception("Event times not in expected order. Was " + recordedOrder.get(1) + " but expected " + actualOrder.get(1));
  88             }
  89         }
  90     }
  91 
  92     private static void printTimedEvents(String heading, List<TimeEvent> recordedOrder) {
  93         System.out.println();
  94         System.out.println(heading);
  95         System.out.println("======================");
  96         for (TimeEvent t : recordedOrder) {
  97             System.out.println(t.toString());
  98         }
  99     }
 100 
 101     private static MyEvent beginEvent(int id) throws Exception {
 102         MyEvent event = new MyEvent(id);
 103         event.begin();
 104         if (!CommonHelper.hasFastTimeEnabled()) {
 105             CommonHelper.waitForSystemCurrentMillisToChange();;
 106         }
 107         actualOrder.add(new TimeEvent(id, true));
 108         return event;
 109     }
 110 
 111     private static void endEvent(MyEvent event) throws Exception {
 112         event.end();
 113         if (!CommonHelper.hasFastTimeEnabled()) {
 114             CommonHelper.waitForSystemCurrentMillisToChange();;
 115         }
 116         event.commit();
 117         actualOrder.add(new TimeEvent(event.id, false));
 118     }
 119 
 120     private final static class TimeEvent implements Comparable<TimeEvent> {
 121         long id;
 122         private boolean begin;
 123         private Instant time;
 124 
 125         public TimeEvent(int id, boolean begin) {
 126             this.id = id;
 127             this.begin = begin;
 128         }
 129 
 130         public TimeEvent(int id, boolean begin, Instant time) {
 131             this(id, begin);
 132             this.time = time;
 133         }
 134 
 135         @Override
 136         public int compareTo(TimeEvent that) {
 137             return this.time.compareTo(that.time);
 138         }
 139 
 140         public String toString() {
 141             StringBuilder sb = new StringBuilder();
 142             if (begin) {
 143                 sb.append("begin");
 144             } else {
 145                 sb.append("end");
 146             }
 147             sb.append("Event");
 148             sb.append("(");
 149             sb.append(id);
 150             sb.append(")");
 151             return sb.toString();
 152         }
 153 
 154         public boolean equals(Object thatObject) {
 155             if (thatObject instanceof TimeEvent) {
 156                 TimeEvent that = (TimeEvent) thatObject;
 157                 return that.id == this.id && that.begin == this.begin;
 158             }
 159             return false;
 160         }
 161     }
 162 
 163     private static RecordedEvent findEvent(int id, List<RecordedEvent> events) {
 164         for (RecordedEvent event : events) {
 165             if (!event.getEventType().getName().equals(EventNames.CPUTimeStampCounter)) {
 166                 int eventId = Events.assertField(event, "id").getValue();
 167                 if (eventId == id) {
 168                     return event;
 169                 }
 170             }
 171         }
 172         Asserts.fail("No event with id " + id);
 173         return null;
 174     }
 175 
 176     private static class MyEvent extends Event {
 177         int id;
 178 
 179         public MyEvent(int id) {
 180             this.id = id;
 181         }
 182     }
 183 }