1 /*
   2  * Copyright (c) 2018, 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.test.lib.Asserts;
  37 import jdk.test.lib.jfr.CommonHelper;
  38 import jdk.test.lib.jfr.EventNames;
  39 import jdk.test.lib.jfr.Events;
  40 
  41 /**
  42  * @test
  43  * @summary Test getStartTime() and getEndTime(). Verify startTime <= endTime
  44  * @key jfr
  45  *
  46  * @library /lib /
  47  * @run main/othervm jdk.jfr.api.recording.event.TestEventTime
  48  */
  49 public class TestEventTime {
  50 
  51     static List<TimeEvent> actualOrder = new ArrayList<>();
  52 
  53     public static void main(String[] args) throws Throwable {
  54         Recording r = new Recording();
  55         r.enable(MyEvent.class).withoutStackTrace();
  56         // for debugging time related issues
  57         r.enable(EventNames.CPUTimeStampCounter);
  58         r.start();
  59         MyEvent event1 = beginEvent(1);
  60         MyEvent event2 = beginEvent(2);
  61         endEvent(event1);
  62         MyEvent event3 = beginEvent(3);
  63         endEvent(event2);
  64         endEvent(event3);
  65 
  66         r.stop();
  67 
  68         List<RecordedEvent> events = Events.fromRecording(r);
  69 
  70         RecordedEvent recEvent1 = findEvent(1, events);
  71         RecordedEvent recEvent2 = findEvent(2, events);
  72         RecordedEvent recEvent3 = findEvent(3, events);
  73 
  74         List<TimeEvent> recordedOrder = new ArrayList<>();
  75         recordedOrder.add(new TimeEvent(1, true, recEvent1.getStartTime()));
  76         recordedOrder.add(new TimeEvent(1, false, recEvent1.getEndTime()));
  77         recordedOrder.add(new TimeEvent(2, true, recEvent2.getStartTime()));
  78         recordedOrder.add(new TimeEvent(2, false, recEvent2.getEndTime()));
  79         recordedOrder.add(new TimeEvent(3, true, recEvent3.getStartTime()));
  80         recordedOrder.add(new TimeEvent(3, false, recEvent3.getEndTime()));
  81         Collections.sort(recordedOrder);
  82 
  83         printTimedEvents("Actual order", actualOrder);
  84         printTimedEvents("Recorded order", recordedOrder);
  85 
  86         for (int i = 0; i < 6; i++) {
  87             if (!actualOrder.get(i).equals(recordedOrder.get(i))) {
  88                 throw new Exception("Event times not in expected order. Was " + recordedOrder.get(1) + " but expected " + actualOrder.get(1));
  89             }
  90         }
  91     }
  92 
  93     private static void printTimedEvents(String heading, List<TimeEvent> recordedOrder) {
  94         System.out.println();
  95         System.out.println(heading);
  96         System.out.println("======================");
  97         for (TimeEvent t : recordedOrder) {
  98             System.out.println(t.toString());
  99         }
 100     }
 101 
 102     private static MyEvent beginEvent(int id) throws Exception {
 103         MyEvent event = new MyEvent(id);
 104         event.begin();
 105         if (!CommonHelper.hasFastTimeEnabled()) {
 106             CommonHelper.waitForSystemCurrentMillisToChange();;
 107         }
 108         actualOrder.add(new TimeEvent(id, true));
 109         return event;
 110     }
 111 
 112     private static void endEvent(MyEvent event) throws Exception {
 113         event.end();
 114         if (!CommonHelper.hasFastTimeEnabled()) {
 115             CommonHelper.waitForSystemCurrentMillisToChange();;
 116         }
 117         event.commit();
 118         actualOrder.add(new TimeEvent(event.id, false));
 119     }
 120 
 121     private final static class TimeEvent implements Comparable<TimeEvent> {
 122         long id;
 123         private boolean begin;
 124         private Instant time;
 125 
 126         public TimeEvent(int id, boolean begin) {
 127             this.id = id;
 128             this.begin = begin;
 129         }
 130 
 131         public TimeEvent(int id, boolean begin, Instant time) {
 132             this(id, begin);
 133             this.time = time;
 134         }
 135 
 136         @Override
 137         public int compareTo(TimeEvent that) {
 138             return this.time.compareTo(that.time);
 139         }
 140 
 141         public String toString() {
 142             StringBuilder sb = new StringBuilder();
 143             if (begin) {
 144                 sb.append("begin");
 145             } else {
 146                 sb.append("end");
 147             }
 148             sb.append("Event");
 149             sb.append("(");
 150             sb.append(id);
 151             sb.append(")");
 152             return sb.toString();
 153         }
 154 
 155         public boolean equals(Object thatObject) {
 156             if (thatObject instanceof TimeEvent) {
 157                 TimeEvent that = (TimeEvent) thatObject;
 158                 return that.id == this.id && that.begin == this.begin;
 159             }
 160             return false;
 161         }
 162     }
 163 
 164     private static RecordedEvent findEvent(int id, List<RecordedEvent> events) {
 165         for (RecordedEvent event : events) {
 166             if (!event.getEventType().getName().equals(EventNames.CPUTimeStampCounter)) {
 167                 int eventId = Events.assertField(event, "id").getValue();
 168                 if (eventId == id) {
 169                     return event;
 170                 }
 171             }
 172         }
 173         Asserts.fail("No event with id " + id);
 174         return null;
 175     }
 176 
 177     private static class MyEvent extends Event {
 178         int id;
 179 
 180         public MyEvent(int id) {
 181             this.id = id;
 182         }
 183     }
 184 }