gt:         VoltProjectBuilder builder = new VoltProjectBuilder();
context: /* This file is part of VoltDB.
   * Copyright (C) 2008-2015 VoltDB Inc.
   *
   * Permission is hereby granted, free of charge, to any person obtaining
   * a copy of this software and associated documentation files (the
   * "Software"), to deal in the Software without restriction, including
   * without limitation the rights to use, copy, modify, merge, publish,
   * distribute, sublicense, and/or sell copies of the Software, and to
   * permit persons to whom the Software is furnished to do so, subject to
   * the following conditions:
   *
   * The above copyright notice and this permission notice shall be
   * included in all copies or substantial portions of the Software.
   *
   * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
   * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
   * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
   * IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
   * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
   * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
   * OTHER DEALINGS IN THE SOFTWARE.
   */
  
  package org.voltdb;
  
  import java.io.File;
  import java.util.HashMap;
  import java.util.Map;
  
  import junit.framework.Assert;
  import junit.framework.TestCase;
  
  import org.voltdb.VoltDB.Configuration;
  import org.voltdb.client.Client;
  import org.voltdb.client.ClientFactory;
  import org.voltdb.client.ClientUtils;
  import org.voltdb.common.Constants;
  import org.voltdb.compiler.VoltProjectBuilder;
  import org.voltdb.utils.FakeStatsProducer;
  import org.voltdb.utils.MiscUtils;
  import org.voltdb.utils.PlatformProperties;
  import org.voltdb.utils.SystemStatsCollector;
  import org.voltdb.utils.SystemStatsCollector.Datum;
  
  public class TestMemoryResourceMonitor extends TestCase
  {
      private static final int MONITORING_INTERVAL = 2;
      private static final int DEFAULT_MONITORING_INTERVAL = 60;
  
      private ServerThread m_localServer;
      private VoltDB.Configuration m_config;
      private Client m_client;
      private TestStatsProducer m_mockStatsProducer;
  
      public void setUpServer(String rssLimit, boolean setMonitoringInterval) throws Exception
      {
          VoltProjectBuilder builder = new VoltProjectBuilder();
          if (rssLimit!=null) {
              builder.setRssLimit(rssLimit);
          }
          if (setMonitoringInterval) {
              builder.setResourceCheckInterval(MONITORING_INTERVAL);
          }
          boolean success = builder.compile(Configuration.getPathToCatalogForTest("resourcemonitor.jar"), 1, 1, 0);
          assert(success);
          MiscUtils.copyFile(builder.getPathToDeployment(), Configuration.getPathToCatalogForTest("resourcemonitor.xml"));
  
          m_config = new VoltDB.Configuration();
          m_config.m_pathToCatalog = Configuration.getPathToCatalogForTest("resourcemonitor.jar");
          m_config.m_pathToDeployment = Configuration.getPathToCatalogForTest("resourcemonitor.xml");
          m_localServer = new ServerThread(m_config);
          m_localServer.start();
          m_localServer.waitForInitialization();
  
          m_mockStatsProducer = new TestStatsProducer();
          SystemStatsCollector.setFakeStatsProducer(m_mockStatsProducer);
  
          assertEquals(OperationMode.RUNNING, VoltDB.instance().getMode());
          m_client = ClientFactory.createClient();
          m_client.createConnection("localhost:" + m_config.m_adminPort);
      }
  
      @Override
      public void tearDown() throws Exception {
          if (m_client != null) {
              m_client.close();
          }
          if (m_localServer != null) {
              m_localServer.shutdown();
          }
      }
  
      public void testBadRssValues() throws Exception {
          String[] badValues = { "xx%",
                  "-1%",
                  "100%",
                  "150%",
                  "40.3%",
                  "-20",
                  "abc"
          };
          ResourceUsageMonitor monitor = new ResourceUsageMonitor(null, null);
          for (int i=0; i<badValues.length; i++) {
              try {
                  monitor.getMemoryLimitSize(badValues[i]);
                  fail("Must have failed for bad memory limit value " + badValues[i]);
              } catch(IllegalArgumentException e) {
                  // expected
              }
          }
      }
  
      public void testGoodRssValues() throws Exception {
          long totalSize = PlatformProperties.getPlatformProperties().ramInMegabytes*1048576L;
          Map<String, Double> configToExpectedRss = new HashMap<>();
          configToExpectedRss.put("0%", 0.0);
          configToExpectedRss.put("1%", totalSize/100.0);
          configToExpectedRss.put("15%", totalSize*15/100.0);
          configToExpectedRss.put("40", 40.0*1073741824L);
          configToExpectedRss.put("1.5", 1.5*1073741824L);
          ResourceUsageMonitor monitor = new ResourceUsageMonitor(null, null);
          for (String str : configToExpectedRss.keySet()) {
              Assert.assertEquals(configToExpectedRss.get(str), monitor.getMemoryLimitSize(str));
          }
      }
  
      public void testNoRssLimit() throws Exception
      {
          setUpServer(null, true);
  
          // Wait for monitoring interval time and verify server is still in running mode
          m_mockStatsProducer.m_rss = 2048L*1024*1024;
          resumeAndWait(MONITORING_INTERVAL+1);
          assertEquals(OperationMode.RUNNING, VoltDB.instance().getMode());
      }
  
      // Disabling this test because it takes long. Enable it and run manually to test.
      public void notestNoMonitoringInterval() throws Exception
      {
          setUpServer("0.5", false);
  
          // Wait for monitoring interval time and verify server is still in running mode
          m_mockStatsProducer.m_rss = 2048L*1024*1024;
          resumeAndWait(DEFAULT_MONITORING_INTERVAL+1);
          assertEquals(OperationMode.RUNNING, VoltDB.instance().getMode());
      }
  
      public void testLimitNotExceeded() throws Exception
      {
          setUpServer("0.5", true);
  
          m_mockStatsProducer.m_rss = 10*1024*1024;
          assertEquals(m_mockStatsProducer.m_rss, SystemStatsCollector.getRSSMB());
  
          // Wait for monitoring interval time and verify server is still in running mode
          resumeAndWait(MONITORING_INTERVAL+1);
          assertEquals(OperationMode.RUNNING, VoltDB.instance().getMode());
      }
  
      public void testLimitNotExceededPerc() throws Exception
      {
          setUpServer("90%", true);
  
          m_mockStatsProducer.m_rss = Double.valueOf(PlatformProperties.getPlatformProperties().ramInMegabytes*1048576L*80/100.0).longValue();
          assertEquals(m_mockStatsProducer.m_rss, SystemStatsCollector.getRSSMB());
  
          // Wait for monitoring interval time and verify server is still in running mode
          resumeAndWait(MONITORING_INTERVAL+1);
          assertEquals(OperationMode.RUNNING, VoltDB.instance().getMode());
      }
  
      public void testLimitExceededWithResumePauseAgain() throws Exception
      {
          setUpServer("0.5", true);
  
          // Go above limit, wait for more than configured amt of time and verify server is paused
          m_mockStatsProducer.m_rss = 512*1024*1024;
          resumeAndWait(MONITORING_INTERVAL+1);
          assertEquals(OperationMode.PAUSED, VoltDB.instance().getMode());
  
          // Resume and verify that server again goes into paused.
          m_client.callProcedure("@Resume");
          resumeAndWait(MONITORING_INTERVAL+1);
          assertEquals(OperationMode.PAUSED, VoltDB.instance().getMode());
      }
  
      public void testLimitExceededWithResume() throws Exception
      {
          setUpServer("0.5", true);
  
          // Go above limit, wait for more than configured amt of time and verify server is paused
          m_mockStatsProducer.m_rss = 512*1024*1024;
          resumeAndWait(MONITORING_INTERVAL+1);
          assertEquals(OperationMode.PAUSED, VoltDB.instance().getMode());
  
          // Don't go above limit in mock, resume and make sure server does not go back into paused.
          m_mockStatsProducer.m_rss = 1024*1024;
          resumeAndWait(MONITORING_INTERVAL+1);
          assertEquals(OperationMode.RUNNING, VoltDB.instance().getMode());
      }
  
      public void testLimitExceededWithResumePerc() throws Exception
      {
          setUpServer("90%", true);
  
          // Go above limit, wait for more than configured amt of time and verify server is paused
          m_mockStatsProducer.m_rss = Double.valueOf(PlatformProperties.getPlatformProperties().ramInMegabytes*1048576L*95/100.0).longValue();
          resumeAndWait(MONITORING_INTERVAL+1);
          assertEquals(OperationMode.PAUSED, VoltDB.instance().getMode());
  
          // Don't go above limit in mock, resume and make sure server does not go back into paused.
          m_mockStatsProducer.m_rss = Double.valueOf(PlatformProperties.getPlatformProperties().ramInMegabytes*1048576L*80/100.0).longValue();
          resumeAndWait(MONITORING_INTERVAL+1);
          assertEquals(OperationMode.RUNNING, VoltDB.instance().getMode());
      }
  
      public void testCatalogUpdate_PauseAfterUpdate() throws Exception
      {
          setUpServer(null, true); // set up server with no rss limit
          m_mockStatsProducer.m_rss = 2048L*1024*1024;
          resumeAndWait(MONITORING_INTERVAL+1);
          assertEquals(OperationMode.RUNNING, VoltDB.instance().getMode());
  
          // update server with rss limit
          String newDepFile = getDeploymentPathWithRss("1");
          String depBytes = new String(ClientUtils.fileToBytes(new File(newDepFile)), Constants.UTF8ENCODING);
          VoltTable[] results = m_client.callProcedure("@UpdateApplicationCatalog", null, depBytes).getResults();
          assertTrue(results.length == 1);
          Thread.sleep(5000); // wait to make sure new deployment file takes effect
  
          resumeAndWait(MONITORING_INTERVAL+1);
          assertEquals(OperationMode.PAUSED, VoltDB.instance().getMode());
      }
  
      public void testCatalogUpdate_ResumeAfterUpdate() throws Exception
      {
          setUpServer("0.5", true); // set up server with rss limit
          m_mockStatsProducer.m_rss = 2048L*1024*1024;
          resumeAndWait(MONITORING_INTERVAL+1);
          assertEquals(OperationMode.PAUSED, VoltDB.instance().getMode());
  
          // update server with rss limit
          String newDepFile = getDeploymentPathWithRss("0");
          String depBytes = new String(ClientUtils.fileToBytes(new File(newDepFile)), Constants.UTF8ENCODING);
          VoltTable[] results = m_client.callProcedure("@UpdateApplicationCatalog", null, depBytes).getResults();
          assertTrue(results.length == 1);
          Thread.sleep(5000); // wait to make sure new deployment file takes effect
  
          resumeAndWait(MONITORING_INTERVAL+1);
          assertEquals(OperationMode.RUNNING, VoltDB.instance().getMode());
      }
  
      private String getDeploymentPathWithRss(String rssLimit) throws Exception
      {
  