1 /*
   2  * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
   3  * 
   4  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   5  *
   6  * The contents of this file are subject to the terms of either the Universal Permissive License
   7  * v 1.0 as shown at http://oss.oracle.com/licenses/upl
   8  *
   9  * or the following license:
  10  *
  11  * Redistribution and use in source and binary forms, with or without modification, are permitted
  12  * provided that the following conditions are met:
  13  * 
  14  * 1. Redistributions of source code must retain the above copyright notice, this list of conditions
  15  * and the following disclaimer.
  16  * 
  17  * 2. Redistributions in binary form must reproduce the above copyright notice, this list of
  18  * conditions and the following disclaimer in the documentation and/or other materials provided with
  19  * the distribution.
  20  * 
  21  * 3. Neither the name of the copyright holder nor the names of its contributors may be used to
  22  * endorse or promote products derived from this software without specific prior written permission.
  23  * 
  24  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR
  25  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
  26  * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
  27  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  28  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
  29  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
  30  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY
  31  * WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  32  */
  33 package org.openjdk.jmc.rjmx.services.jfr.test;
  34 
  35 import static org.junit.Assert.assertEquals;
  36 import static org.junit.Assert.assertNotNull;
  37 import static org.junit.Assert.fail;
  38 import static org.openjdk.jmc.common.unit.UnitLookup.MILLISECOND;
  39 import static org.openjdk.jmc.common.unit.UnitLookup.SECOND;
  40 
  41 import java.util.Date;
  42 import java.util.Map;
  43 import java.util.Properties;
  44 
  45 import org.junit.Test;
  46 import org.openjdk.jmc.common.unit.IConstrainedMap;
  47 import org.openjdk.jmc.common.unit.IMutableConstrainedMap;
  48 import org.openjdk.jmc.common.unit.IOptionDescriptor;
  49 import org.openjdk.jmc.common.unit.IQuantity;
  50 import org.openjdk.jmc.common.unit.UnitLookup;
  51 import org.openjdk.jmc.flightrecorder.configuration.internal.ValidationToolkit;
  52 import org.openjdk.jmc.flightrecorder.configuration.recording.RecordingOptionsBuilder;
  53 import org.openjdk.jmc.rjmx.services.jfr.IFlightRecorderService;
  54 import org.openjdk.jmc.rjmx.services.jfr.IRecordingDescriptor;
  55 
  56 @SuppressWarnings("nls")
  57 public class RecordingOptionsTest extends JfrTestCase {
  58 
  59         @Test
  60         public void testGetAvailableOptions() throws Exception {
  61                 assumeHotSpot7u12OrLater(getConnectionHandle());
  62 
  63                 IFlightRecorderService service = getFlightRecorderService();
  64                 Map<String, IOptionDescriptor<?>> data = service.getAvailableRecordingOptions();
  65                 assertNotNull(data);
  66         }
  67 
  68         @Test
  69         public void testGetOptionsFromRecording() throws Exception {
  70                 assumeHotSpot7u12OrLater(getConnectionHandle());
  71 
  72                 IFlightRecorderService service = getFlightRecorderService();
  73                 IRecordingDescriptor recording = startContinuousRecording();
  74                 IConstrainedMap<String> data = service.getRecordingOptions(getContinuousRecording());
  75                 assertNotNull(data);
  76                 stopRecording(recording);
  77         }
  78 
  79         @Test
  80         public void testValidateOption() throws Exception {
  81                 RecordingOptionsBuilder builder = new RecordingOptionsBuilder(getFlightRecorderService());
  82                 builder.addByKey(RecordingOptionsBuilder.KEY_DURATION, "20s");
  83                 IConstrainedMap<String> options = builder.build();
  84                 try {
  85                         ValidationToolkit.validate(options);
  86                 } catch (Exception e) {
  87                         throw e;
  88                 }
  89         }
  90 
  91         @Test
  92         public void testValidateInvalidOption() throws Exception {
  93                 IFlightRecorderService service = getFlightRecorderService();
  94                 IMutableConstrainedMap<String> options = service.getDefaultRecordingOptions().emptyWithSameConstraints();
  95                 try {
  96                         // Not allowed to put string representations directly in options map anymore.
  97                         options.put(RecordingOptionsBuilder.KEY_DURATION, "20s");
  98                         fail("Expected exception to be thrown for invalid options");
  99                 } catch (Exception expected) {
 100                 }
 101                 ValidationToolkit.validate(options);
 102         }
 103 
 104         @Test
 105         public void testStringOptions() throws Exception {
 106                 RecordingOptionsBuilder builder = new RecordingOptionsBuilder(getFlightRecorderService());
 107                 builder.addByKey(RecordingOptionsBuilder.KEY_DURATION, "20s");
 108                 IConstrainedMap<String> map = builder.build();
 109                 assertSame(SECOND.quantity(20), (IQuantity) map.get(RecordingOptionsBuilder.KEY_DURATION));
 110         }
 111 
 112         @Test
 113         public void testCreateOptionsMapFromStrings() throws Exception {
 114                 Properties props = new Properties();
 115                 IFlightRecorderService service = getFlightRecorderService();
 116                 RecordingOptionsBuilder builder = new RecordingOptionsBuilder(service);
 117                 boolean hasCompressed = "1.0".equals(service.getVersion());
 118                 props.put(RecordingOptionsBuilder.KEY_DURATION, "45 ms");
 119                 Date myDate = new Date();
 120                 if (hasCompressed) {
 121                         props.put(RecordingOptionsBuilder.KEY_DESTINATION_FILE, "myfile");
 122                         props.put(RecordingOptionsBuilder.KEY_DESTINATION_COMPRESSED, "true");
 123                         // FIXME: Do we really want to support parsing Date.toString() format?
 124 //                      props.put(RecordingOptionsBuilder.KEY_START_TIME, myDate.toString());
 125                         props.put(RecordingOptionsBuilder.KEY_START_TIME, Long.toString(myDate.getTime()));
 126                 }
 127                 IConstrainedMap<String> options = builder.fromProperties(props).build();
 128                 assertSame(MILLISECOND.quantity(45), (IQuantity) options.get(RecordingOptionsBuilder.KEY_DURATION));
 129                 if (hasCompressed) {
 130                         assertEquals("myfile", options.get(RecordingOptionsBuilder.KEY_DESTINATION_FILE));
 131                         assertEquals(Boolean.TRUE, options.get(RecordingOptionsBuilder.KEY_DESTINATION_COMPRESSED));
 132                         assertSame(UnitLookup.fromDate(myDate), (IQuantity) options.get(RecordingOptionsBuilder.KEY_START_TIME));
 133                 }
 134         }
 135 }