/*
 * Copyright (c) 2014, 2017, Oracle and/or its affiliates. All rights reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
 */

/*
 * @test
 * @bug 8054823
 * @summary Tests the setFlag and printFlag attach command
 * @library /test/lib
 * @modules java.base/jdk.internal.misc
 *          java.compiler
 *          java.management
 *          jdk.attach/sun.tools.attach
 *          jdk.internal.jvmstat/sun.jvmstat.monitor
 * @run main AttachSetGetFlag
 */

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.InputStream;
import java.lang.reflect.Field;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;

import sun.tools.attach.HotSpotVirtualMachine;

import jdk.test.lib.Asserts;
import jdk.test.lib.Platform;
import jdk.test.lib.process.ProcessTools;
import com.sun.tools.attach.VirtualMachine;

public class AttachSetGetFlag {

  public static void main(String... args) throws Exception {
    // Test a manageable uintx flag.
    testGetFlag("MaxHeapFreeRatio", "60");
    testSetFlag("MaxHeapFreeRatio", "50", "60");

    // Test a non-manageable size_t flag.
    // Since it is not manageable, we can't test the setFlag functionality.
    testGetFlag("ArrayAllocatorMallocLimit", "128");
    // testSetFlag("ArrayAllocatorMallocLimit", "64", "128");

    // Test a uint flag.
    testGetFlag("ParallelGCThreads", "10");
  }

  public static ProcessBuilder runTarget(String flagName, String flagValue) throws Exception {
    return ProcessTools.createJavaProcessBuilder(
        "-XX:+UnlockExperimentalVMOptions",
        "-XX:" + flagName + "=" + flagValue,
        "AttachSetGetFlag$Target");
  }

  public static void testGetFlag(String flagName, String flagValue) throws Exception {
    ProcessBuilder pb = runTarget(flagName, flagValue);

    Process target = pb.start();

    try {
      waitForReady(target);

      int pid = (int)target.getPid();

      HotSpotVirtualMachine vm = (HotSpotVirtualMachine)VirtualMachine.attach(((Integer)pid).toString());

      // Test Get
      BufferedReader remoteDataReader = new BufferedReader(new InputStreamReader(
          vm.printFlag(flagName)));

      boolean foundExpectedLine = false;

      String line = null;
      while((line = remoteDataReader.readLine()) != null) {
        System.out.println("printFlag: " + line);
        if (line.equals("-XX:" + flagName + "=" + flagValue)) {
          foundExpectedLine = true;
        }
      }

      Asserts.assertTrue(foundExpectedLine, "Didn't get the expected output: '-XX:" + flagName + "=" + flagValue + "'");

      vm.detach();
    }
    finally {
      target.destroy();
      target.waitFor();
    }
  }

  public static void testSetFlag(String flagName, String initialFlagValue, String flagValue) throws Exception {
    ProcessBuilder pb = runTarget(flagName, initialFlagValue);

    Process target = pb.start();

    try {
      waitForReady(target);

      int pid = (int)target.getPid();

      HotSpotVirtualMachine vm = (HotSpotVirtualMachine)VirtualMachine.attach(((Integer)pid).toString());

      // First set the value.
      BufferedReader remoteDataReader = new BufferedReader(new InputStreamReader(
          vm.setFlag(flagName, flagValue)));

      String line;
      while((line = remoteDataReader.readLine()) != null) {
        System.out.println("setFlag: " + line);
        // Just empty the stream.
      }
      remoteDataReader.close();

      // Then read and make sure we get back the set value.
      remoteDataReader = new BufferedReader(new InputStreamReader(vm.printFlag(flagName)));

      boolean foundExpectedLine = false;
      line = null;
      while((line = remoteDataReader.readLine()) != null) {
        System.out.println("getFlag: " + line);
        if (line.equals("-XX:" + flagName + "=" + flagValue)) {
          foundExpectedLine = true;
        }
      }

      Asserts.assertTrue(foundExpectedLine, "Didn't get the expected output: '-XX:" + flagName + "=" + flagValue + "'");

      vm.detach();

    } finally {
      target.destroy();
      target.waitFor();
    }
  }

  private static void waitForReady(Process target) throws Exception {
    InputStream os = target.getInputStream();
    try (BufferedReader reader = new BufferedReader(new InputStreamReader(os))) {
      String line;
      while ((line = reader.readLine()) != null) {
        if ("Ready".equals(line)) {
          return;
        }
      }
    }
  }


  public static class Target {
    public static void main(String [] args) throws Exception {
      System.out.println("Ready");
      System.out.flush();
      while (true) {
        Thread.sleep(1000);
      }
    }
  }
}
