text:
package org.bitcoins.script.arithmetic

import org.bitcoins.script.control.{ControlOperationsInterpreter, OP_VERIFY}
import org.bitcoins.script.flag.ScriptFlagUtil
import org.bitcoins.script.result.{ScriptErrorMinimalData, ScriptErrorInvalidStackOperation, ScriptErrorUnknownError}
import org.bitcoins.script.{ExecutedScriptProgram, PreExecutionScriptProgram, ExecutionInProgressScriptProgram, ScriptProgram}
import org.bitcoins.script.constant._
import org.bitcoins.util.{BitcoinScriptUtil, BitcoinSUtil}

import scala.annotation.tailrec

/**
 * Created by chris on 1/25/16.
 */
trait ArithmeticInterpreter extends ControlOperationsInterpreter {

  /**
   * a is added to b
   * @param program
   * @return
   */
  def opAdd(program : ScriptProgram) : ScriptProgram = {
    require(program.script.headOption.isDefined && program.script.head == OP_ADD, "Script top must be OP_ADD")
    performBinaryArithmeticOperation(program, (x,y) => x + y)
  }

  /**
   * Increments the stack top by 1
   * @param program
   * @return
   */
  def op1Add(program : ScriptProgram) : ScriptProgram = {
    require(program.script.headOption.isDefined && program.script.head == OP_1ADD, "Script top must be OP_1ADD")
    performUnaryArithmeticOperation(program, x => x + ScriptNumber.one)
  }

  /**
   * Decrements the stack top by 1
   * @param program
   * @return
   */
  def op1Sub(program : ScriptProgram) : ScriptProgram = {
    require(program.script.headOption.isDefined && program.script.head == OP_1SUB, "Script top must be OP_1SUB")
    performUnaryArithmeticOperation(program, x => x - ScriptNumber.one )
  }

  /**
   * b is subtracted from a.
   * @param program
   * @return
   */
  def opSub(program : ScriptProgram) : ScriptProgram = {
    require(program.script.headOption.isDefined && program.script.head == OP_SUB, "Script top must be OP_SUB")
    performBinaryArithmeticOperation(program, (x,y) => y - x)
  }

  /**
   * Takes the absolute value of the stack top
   * @param program
   * @return
   */
  def opAbs(program : ScriptProgram) : ScriptProgram = {
    require(program.script.headOption.isDefined && program.script.head == OP_ABS, "Script top must be OP_ABS")
    performUnaryArithmeticOperation(program, x => x match {
      case ScriptNumber.zero => ScriptNumber.zero
      case _ : ScriptNumber => ScriptNumber(x.num.abs)
    })
  }

  /**
   * Negates the stack top
   * @param program
   * @return
   */
  def opNegate(program : ScriptProgram) : ScriptProgram = {
    require(program.script.headOption.isDefined && program.script.head == OP_NEGATE, "Script top must be OP_NEGATE")
    performUnaryArithmeticOperation(program, x => x -)
  }

  /**
   * If the input is 0 or 1, it is flipped. Otherwise the output will be 0.
   * @param program
   * @return
   */
  def opNot(program : ScriptProgram) : ScriptProgram = {
    require(program.script.headOption.isDefined && program.script.head == OP_NOT, "Script top must be OP_NOT")

    performUnaryArithmeticOperation(program, x => if (program.stackTopIsFalse) OP_TRUE else OP_FALSE)
  }

  /**
   * Returns 0 if the input is 0. 1 otherwise.
   * @param program
   * @return
   */
  def op0NotEqual(program : ScriptProgram) : ScriptProgram = {
    require(program.script.headOption.isDefined && program.script.head == OP_0NOTEQUAL, "Script top must be OP_0NOTEQUAL")
    performUnaryArithmeticOperation(program, x => if(x.num == 0) OP_FALSE else OP_TRUE)
  }

  /**
   * 	If both a and b are not 0, the output is 1. Otherwise 0.
   * @param program
   * @return
   */
  def opBoolAnd(program : ScriptProgram) : ScriptProgram = {
    require(program.script.headOption.isDefined && program.script.head == OP_BOOLAND, "Script top must be OP_BOOLAND")
    performBinaryBooleanOperation(program,(x,y) => {
      val xIsFalse = (x == ScriptNumber.zero || x == OP_0)
      val yIsFalse = (y == ScriptNumber.zero || y == OP_0)
      if (xIsFalse || yIsFalse) false else true
    })

  }

  /**
   * If a or b is not 0, the output is 1. Otherwise 0.
   * @param program
   * @return
   */
  def opBoolOr(program : ScriptProgram) : ScriptProgram = {
    require(program.script.headOption.isDefined && program.script.head == OP_BOOLOR, "Script top must be OP_BOOLOR")
    performBinaryBooleanOperation(program, (x,y) => {
      if (x == y && (x == ScriptNumber.zero || x == OP_0)) false else true
    })
  }

  /**
   * Returns 1 if the numbers are equal, 0 otherwise.
   * @param program
   * @return
   */
  def opNumEqual(program : ScriptProgram) : ScriptProgram = {
    require(program.script.headOption.isDefined && program.script.head == OP_NUMEQUAL, "Script top must be OP_NUMEQUAL")
    performBinaryBooleanOperation(program,(x,y) => x.numEqual(y))
  }

  /**
   * Same as OP_NUMEQUAL, but runs OP_VERIFY afterward.
   * @param program
   * @return
   */
  def opNumEqualVerify(program : ScriptProgram) : ScriptProgram = {
    require(program.script.headOption.isDefined && program.script.head == OP_NUMEQUALVERIFY,
      "Script top must be OP_NUMEQUALVERIFY")
    if (program.stack.size < 2) {
      logger.error("OP_NUMEQUALVERIFY requires two stack elements")
      ScriptProgram(program,ScriptErrorInvalidStackOperation)
    } else {
      val numEqualProgram = ScriptProgram(program, program.stack, OP_NUMEQUAL :: program.script.tail)
      val numEqualResult = opNumEqual(numEqualProgram)
      numEqualResult match {
        case _ : ExecutionInProgressScriptProgram =>
          val verifyProgram = ScriptProgram(numEqualResult, numEqualResult.stack, OP_VERIFY :: numEqualResult.script)
          val verifyResult = opVerify(verifyProgram)
          verifyResult
        case _ : PreExecutionScriptProgram | _ : ExecutedScriptProgram =>
          numEqualResult
      }
    }
  }

  /**
   * 	Returns 1 if the numbers are not equal, 0 otherwise.
   * @param program
   * @return
   */
  def opNumNotEqual(program : ScriptProgram) : ScriptProgram = {
    require(program.script.headOption.isDefined && program.script.head == OP_NUMNOTEQUAL,
      "Script top must be OP_NUMNOTEQUAL")
    performBinaryBooleanOperation(program, (x,y) => {
      x.num != y.num
    })
  }

  /**
   * 	Returns 1 if a is less than b, 0 otherwise.
   * @param program
   * @return
   */
  def opLessThan(program : ScriptProgram) : ScriptProgram = {
    require(program.script.headOption.isDefined && program.script.head == OP_LESSTHAN,
      "Script top must be OP_LESSTHAN")
    performBinaryBooleanOperation(program, (x,y) => y < x)
  }

  /**
   * 	Returns 1 if a is greater than b, 0 otherwise.
   * @param program
   * @return
   */
  def opGreaterThan(program : ScriptProgram) : ScriptProgram = {
    require(program.script.headOption.isDefined && program.script.head == OP_GREATERTHAN,
      "Script top must be OP_GREATERTHAN")
    performBinaryBooleanOperation(program, (x,y) => y > x)
  }

  /**
   * Returns 1 if a is less than or equal to b, 0 otherwise.
   * @param program
   * @return
   */
  def opLessThanOrEqual(program : ScriptProgram) : ScriptProgram = {
    require(program.script.headOption.isDefined && program.script.head == OP_LESSTHANOREQUAL,
      "Script top must be OP_LESSTHANOREQUAL")
    performBinaryBooleanOperation(program, (x,y) => y <= x)
  }

  /**
   *	Returns 1 if a is greater than or equal to b, 0 otherwise.
   * @param program
   * @return
   */
  def opGreaterThanOrEqual(program : ScriptProgram) : ScriptProgram = {
    require(program.script.headOption.isDefined && program.script.head == OP_GREATERTHANOREQUAL,
      "Script top must be OP_GREATERTHANOREQUAL")
    performBinaryBooleanOperation(program, (x,y) => y >= x)
  }

  /**
   * Returns the smaller of a and b.
   * @param program
   * @return
   */
  def opMin(program : ScriptProgram) : ScriptProgram = {
    require(program.script.headOption.isDefined && program.script.head == OP_MIN,
      "Script top must be OP_MIN")

    if (program.stack.size < 2) {
      logger.error("OP_MAX requires at least two stack elements")
      ScriptProgram(program,ScriptErrorInvalidStackOperation)
    } else {
      performComparisonOnTwoStackTopItems(program, (x : ScriptNumber, y : ScriptNumber) => if (x < y) x else y)
    }

  }

  /**
   * Returns the larger of a and b.
   * @param program
   * @return
   */
  def opMax(program : ScriptProgram) : ScriptProgram = {
    require(program.script.headOption.isDefined && program.script.head == OP_MAX,
      "Script top must be OP_MAX")
    if (program.stack.size < 2) {
      logger.error("OP_MAX requires at least two stack elements")
      ScriptProgram(program,ScriptErrorInvalidStackOperation)
    } else {
      performComparisonOnTwoStackTopItems(program, (x : ScriptNumber, y : ScriptNumber) => if (x > y) x else y)
    }
  }

  /**
   * Returns 1 if x is within the specified range (left-inclusive), 0 otherwise.
   * @param program
   * @return
   */
  def opWithin(program : ScriptProgram) : ScriptProgram = {
    require(program.script.headOption.isDefined && program.script.head == OP_WITHIN,
      "Script top must be OP_WITHIN")
    if (program.stack.size < 3) {
      logger.error("OP_WITHIN requires at least 3 elements on the stack")
      ScriptProgram(program,ScriptErrorInvalidStackOperation)
    } else {
      val c = ScriptNumber(program.stack.head.bytes)
      val b = ScriptNumber(program.stack.tail.head.bytes)
      val a = ScriptNumber(program.stack.tail.tail.head.bytes)

      if (ScriptFlagUtil.requireMinimalData(program.flags) && (!BitcoinScriptUtil.isShortestEncoding(c) ||
        !BitcoinScriptUtil.isShortestEncoding(b) || !BitcoinScriptUtil.isShortestEncoding(a))) {

        logger.error("The constant you gave us is not encoded in the shortest way possible")
        ScriptProgram(program, ScriptErrorMinimalData)
      } else if (isLargerThan4Bytes(c) || isLargerThan4Bytes(b) || isLargerThan4Bytes(a)) {
        //pretty sure that an error is thrown inside of CScriptNum which in turn is caught by interpreter.cpp here
        //https://github.com/bitcoin/bitcoin/blob/master/src/script/interpreter.cpp#L999-L1002
        logger.error("Cannot perform arithmetic operation on a number larger than 4 bytes, one of these three numbers is larger than 4 bytes: "
          + c + " " + b + " " + a)
        ScriptProgram(program,ScriptErrorUnknownError)
      } else {
        val isWithinRange = a >= b && a < c
        val newStackTop = if (isWithinRange) OP_TRUE else OP_FALSE
        ScriptProgram(program, newStackTop :: program.stack.tail.tail.tail, program.script.tail)
      }

    }

  }

  /**
   * This function checks if a number is <= 4 bytes in size
   * We cannot perform arithmetic operations on bitcoin numbers that are larger than 4 bytes.
   * https://github.com/bitcoin/bitcoin/blob/a6a860796a44a2805a58391a009ba22752f64e32/src/script/script.h#L214-L239
   * @param scriptNumber the script number to be checked
   * @return false if the number is larger than 4 bytes
   */
  private def isLargerThan4Bytes(scriptNumber : ScriptNumber) : Boolean = scriptNumber.bytes.size > 4

  /**
   * Performs the given arithmetic operation on the stack head
   * @param program the program whose stack top is used as an argument for the arithmetic operation
   * @param op the arithmetic ooperation that needs to be executed on the number, for instance incrementing by 1
   * @return the program with the result from performing the arithmetic operation pushed onto the top of the stack
   */
  @tailrec
  private def performUnaryArithmeticOperation(program : ScriptProgram, op : ScriptNumber => ScriptNumber) : ScriptProgram = {
    program.stack.headOption match {
      case None =>
        logger.error("We need one stack element for performing a unary arithmetic operation")
        ScriptProgram(program,ScriptErrorInvalidStackOperation)
      case Some(s : ScriptNumber) =>
        if (ScriptFlagUtil.requireMinimalData(program.flags) && !BitcoinScriptUtil.isShortestEncoding(s)) {
          logger.error("The number you gave us is not encoded in the shortest way possible")
          ScriptProgram(program, ScriptErrorMinimalData)
        } else if (isLargerThan4Bytes(s)) {
          logger.error("Cannot perform arithmetic operation on a number larger than 4 bytes, here is the number: " + s)
          //pretty sure that an error is thrown inside of CScriptNum which in turn is caught by interpreter.cpp here
          //https://github.com/bitcoin/bitcoin/blob/master/src/script/interpreter.cpp#L999-L1002
          ScriptProgram(program,ScriptErrorUnknownError)
        } else {
          val newScriptNumber = op(s)
          ScriptProgram(program, newScriptNumber :: program.stack.tail, program.script.tail)
        }
      case Some(s : ScriptConstant) =>
        if (ScriptFlagUtil.requireMinimalData(program.flags) && !BitcoinScriptUtil.isShortestEncoding(s)) {
          logger.error("The number you gave us is not encoded in the shortest way possible")
          ScriptProgram(program, ScriptErrorUnknownError)
        } else {
          val interpretedNumber = ScriptNumber(BitcoinSUtil.hexToLong(s.hex))
          val newProgram = ScriptProgram(program, interpretedNumber ::  program.stack.tail, ScriptProgram.Stack)
          performUnaryArithmeticOperation(newProgram, op)
        }

      case Some(s : ScriptToken) =>
        //pretty sure that an error is thrown inside of CScriptNum which in turn is caught by interpreter.cpp here
        //https://github.com/bitcoin/bitcoin/blob/master/src/script/interpreter.cpp#L999-L1002
        logger.error("Stack top must be a script number/script constant to perform an arithmetic operation")
        ScriptProgram(program,ScriptErrorUnknownError)
    }
  }

  /**
   * Performs the given arithmetic operation on the top two stack items
   * @param program the program whose stack top is used as an argument for the arithmetic operation
   * @param op the arithmetic ooperation that needs to be executed on the number, for instance incrementing by 1
   * @return the program with the result from performing the arithmetic operation pushed onto the top of the stack
   */
  @tailrec
  private def performBinaryArithmeticOperation(program : ScriptProgram, op : (ScriptNumber, ScriptNumber) => ScriptNumber) : ScriptProgram = {
    if (program.stack.size < 2) {
      logger.error("We must have two elements to perform a binary arithmetic operation")
      ScriptProgram(program,ScriptErrorInvalidStackOperation)
    } else {
      (program.stack.head, program.stack.tail.head) match {
        case (x : ScriptNumber, y : ScriptNumber) =>
          if (ScriptFlagUtil.requireMinimalData(program.flags) && (!BitcoinScriptUtil.isShortestEncoding(x) || !BitcoinScriptUtil.isShortestEncoding(y))) {
            logger.error("The constant you gave us is not encoded in the shortest way possible")
            ScriptProgram(program, ScriptErrorMinimalData)
          } else if (isLargerThan4Bytes(x) || isLargerThan4Bytes(y)) {
            //pretty sure that an error is thrown inside of CScriptNum which in turn is caught by interpreter.cpp here
            //https://github.com/bitcoin/bitcoin/blob/master/src/script/interpreter.cpp#L999-L1002
            logger.error("Cannot perform arithmetic operation on a number larger than 4 bytes, one of these two numbers is larger than 4 bytes: " + x + " " + y)
            ScriptProgram(program,ScriptErrorUnknownError)
          } else {
            val newStackTop = op(x,y)
            ScriptProgram(program,newStackTop :: program.stack.tail.tail,program.script.tail)
          }
        case (x : ScriptConstant, y : ScriptNumber) =>
          if (ScriptFlagUtil.requireMinimalData(program.flags) && !BitcoinScriptUtil.isShortestEncoding(x)) {
            logger.error("The number you gave us is not encoded in the shortest way possible")
            ScriptProgram(program, ScriptErrorMinimalData)
          } else {
            //interpret x as a number
            val interpretedNumber = ScriptNumber(BitcoinSUtil.hexToLong(x.hex))
            val newProgram = ScriptProgram(program, interpretedNumber :: program.stack.tail, ScriptProgram.Stack)
            performBinaryArithmeticOperation(newProgram, op)
          }
        case (x : ScriptNumber, y : ScriptConstant) =>
          if (ScriptFlagUtil.requireMinimalData(program.flags) && !BitcoinScriptUtil.isShortestEncoding(y)) {
            logger.error("The number you gave us is not encoded in the shortest way possible")
            ScriptProgram(program, ScriptErrorMinimalData)
          } else {
          //interpret y as a number
            val interpretedNumber = ScriptNumber(BitcoinSUtil.hexToLong(y.hex))
            val newProgram = ScriptProgram(program, x :: interpretedNumber ::  program.stack.tail, ScriptProgram.Stack)
            performBinaryArithmeticOperation(newProgram, op)
          }
        case (x : ScriptConstant, y : ScriptConstant) =>

          if (ScriptFlagUtil.requireMinimalData(program.flags) && (!BitcoinScriptUtil.isShortestEncoding(x) || !BitcoinScriptUtil.isShortestEncoding(y))) {
            logger.error("The constant you gave us is not encoded in the shortest way possible")
            ScriptProgram(program, ScriptErrorMinimalData)
          } else {
            //interpret x and y as a number
            val interpretedNumberX = ScriptNumber(BitcoinSUtil.hexToLong(x.hex))
            val interpretedNumberY = ScriptNumber(BitcoinSUtil.hexToLong(y.hex))
            val newProgram = ScriptProgram(program, interpretedNumberX :: interpretedNumberY ::  program.stack.tail.tail, ScriptProgram.Stack)
            performBinaryArithmeticOperation(newProgram, op)
          }

        case (x : ScriptToken, y : ScriptToken) =>
          //pretty sure that an error is thrown inside of CScriptNum which in turn is caught by interpreter.cpp here
          //https://github.com/bitcoin/bitcoin/blob/master/src/script/interpreter.cpp#L999-L1002
          logger.error("The top two stack items must be script numbers to perform an arithmetic operation")
          ScriptProgram(program,ScriptErrorUnknownError)
      }
    }

  }

  /**
   * Compares two script numbers with the given boolean operation
   * @param program the program whose two top stack elements are used for the comparison
   * @param op the operation which compares the two script numbers
   * @return the program with either OP_FALSE or OP_TRUE on the stack top
   */
  private def performBinaryBooleanOperation(program : ScriptProgram, op : (ScriptNumber, ScriptNumber) => Boolean) : ScriptProgram = {
    if (program.stack.size < 2) {
      logger.error("We need two stack elements for a binary boolean operation")
      ScriptProgram(program,ScriptErrorInvalidStackOperation)
    } else {

      val (x,y) = parseTopTwoStackElementsAsScriptNumbers(program)
      if (ScriptFlagUtil.requireMinimalData(program.flags) &&
        (!BitcoinScriptUtil.isShortestEncoding(x) || !BitcoinScriptUtil.isShortestEncoding(y))) {
        logger.error("The constant you gave us is not encoded in the shortest way possible")
        ScriptProgram(program, ScriptErrorMinimalData)
      } else if (isLargerThan4Bytes(x) || isLargerThan4Bytes(y)) {
        //pretty sure that an error is thrown inside of CScriptNum which in turn is caught by interpreter.cpp here
        //https://github.com/bitcoin/bitcoin/blob/master/src/script/interpreter.cpp#L999-L1002
        logger.error("Cannot perform boolean operation on a number larger than 4 bytes, one of these two numbers is larger than 4 bytes: " + x + " " + y)
        ScriptProgram(program,ScriptErrorUnknownError)
      } else {
        val newStackTop = if(op(x,y)) OP_TRUE else OP_FALSE
        ScriptProgram(program,newStackTop :: program.stack.tail.tail,program.script.tail)
      }
    }
  }

  /**
   * Takes the top two stack items, parses them to numbers then executes the op function on them and places the result
   * onto the stack top
   * @param program the script program whose two top stack items are used as arguments for op
   * @param op the operation that needs to be executed on the two stack top items
   * @return the program with the result of op pushed onto the top of the stack
   */
  private def performComparisonOnTwoStackTopItems(program : ScriptProgram,
    op : (ScriptNumber, ScriptNumber) => ScriptNumber) : ScriptProgram = {
    performBinaryArithmeticOperation(program,op)
  }

  /**
   * Takes the top two stack elements and parses them as script numbers
   * @param program the program whose top two stack elements are being parsed as script numbers
   * @return the tuple with the first element being the first stack element, the second element in the tuple being the second stack element
   */
  private def parseTopTwoStackElementsAsScriptNumbers(program : ScriptProgram) : (ScriptNumber,ScriptNumber) = {
    (program.stack.head, program.stack.tail.head) match {
      case (x : ScriptNumber, y : ScriptNumber) => (x,y)
      case (x : ScriptConstant, y : ScriptNumber) =>
          val interpretedNumber = ScriptNumber(x.hex)
          (interpretedNumber,y)
      case (x : ScriptNumber, y : ScriptConstant) =>
          //interpret y as a number
          val interpretedNumber = ScriptNumber(y.hex)
        (x,interpretedNumber)
      case (x : ScriptConstant, y : ScriptConstant) =>
          //interpret x and y as a number
          val interpretedNumberX = ScriptNumber(x.hex)
          val interpretedNumberY = ScriptNumber(y.hex)
          (interpretedNumberX,interpretedNumberY)

      case (x : ScriptToken, y : ScriptToken) =>
        //pretty sure that an error is thrown inside of CScriptNum which in turn is caught by interpreter.cpp here
        //https://github.com/bitcoin/bitcoin/blob/master/src/script/interpreter.cpp#L999-L1002
        logger.error("The top two stack items must be script numbers to perform an arithmetic operation")
        throw new RuntimeException("Stack top elements must have be script constants to be interpreted as numbers")
    }
  }
}


text:
namespace gfx {
class Rect;
class Range;
}  // namespace gfx

namespace ui {

class WaylandConnection;
class WaylandWindow;

// Client interface which handles wayland text input callbacks
class ZWPTextInputWrapperClient {
 public:
  virtual ~ZWPTextInputWrapperClient() {}

  // Called when a new composing text (pre-edit) should be set around the
  // current cursor position. Any previously set composing text should
  // be removed.
  virtual void OnPreeditString(const std::string& text,
                               int32_t preedit_cursor) = 0;

  // Called when a complete input sequence has been entered.  The text to
  // commit could be either just a single character after a key press or the
  // result of some composing (pre-edit).
  virtual void OnCommitString(const std::string& text) = 0;

  // Called when client needs to delete all or part of the text surrounding
  // the cursor
  virtual void OnDeleteSurroundingText(int32_t index, uint32_t length) = 0;

  // Notify when a key event was sent. Key events should not be used
  // for normal text input operations, which should be done with
  // commit_string, delete_surrounding_text, etc.
  virtual void OnKeysym(uint32_t key, uint32_t state, uint32_t modifiers) = 0;
};

// A wrapper around different versions of wayland text input protocols.
// Wayland compositors support various different text input protocols which
// all from Chromium point of view provide the functionality needed by Chromium
// IME. This interface collects the functionality behind one wrapper API.
class ZWPTextInputWrapper {
 public:
  virtual ~ZWPTextInputWrapper() {}

  virtual void Initialize(WaylandConnection* connection,
                          ZWPTextInputWrapperClient* client) = 0;

  virtual void Reset() = 0;

  virtual void Activate(WaylandWindow* window) = 0;
  virtual void Deactivate() = 0;

  virtual void ShowInputPanel() = 0;
  virtual void HideInputPanel() = 0;

  virtual void SetCursorRect(const gfx::Rect& rect) = 0;
  virtual void SetSurroundingText(const base::string16& text,
                                  const gfx::Range& selection_range) = 0;
};

}  // namespace ui

#endif  // UI_OZONE_PLATFORM_WAYLAND_HOST_ZWP_TEXT_INPUT_WRAPPER_H_

redpajama_set_name: RedPajamaGithub


text:
using System.IO;
using NUnit.Framework;
using Umbraco.Core.Services;
using Umbraco.Tests.TestHelpers;
using System;
using System.Linq;
using System.Threading;
using Umbraco.Tests.Testing;
using Umbraco.Web.Services;
using Current = Umbraco.Web.Composing.Current;

namespace Umbraco.Tests.TreesAndSections
{

    ///
    ///This is a test class for ApplicationTreeTest and is intended
    ///to contain all ApplicationTreeTest Unit Tests
    ///
    [TestFixture]
    [Apartment(ApartmentState.STA)]
    [UmbracoTest(Database = UmbracoTestOptions.Database.NewSchemaPerTest)]
    public class ApplicationTreeTest : TestWithDatabaseBase
    {
        public override void SetUp()
        {
            base.SetUp();

            var treesConfig = TestHelper.MapPathForTest("~/TEMP/TreesAndSections/trees.config");
            var appConfig = TestHelper.MapPathForTest("~/TEMP/TreesAndSections/applications.config");
            Directory.CreateDirectory(TestHelper.MapPathForTest("~/TEMP/TreesAndSections"));
            using (var writer = File.CreateText(treesConfig))
            {
                writer.Write(ResourceFiles.trees);
            }
            using (var writer = File.CreateText(appConfig))
            {
                writer.Write(ResourceFiles.applications);
            }

            ApplicationTreeService.TreeConfigFilePath = treesConfig;
            SectionService.AppConfigFilePath = appConfig;
        }

        public override void TearDown()
        {
            base.TearDown();

            if (Directory.Exists(TestHelper.MapPathForTest("~/TEMP/TreesAndSections")))
            {
                Directory.Delete(TestHelper.MapPathForTest("~/TEMP/TreesAndSections"), true);
            }
            ApplicationTreeService.TreeConfigFilePath = null;
            SectionService.AppConfigFilePath = null;
        }

        ///
        /// Creates a new app tree linked to an application, then delete the application and make sure the tree is gone as well
        ///
        [Test()]
        public void ApplicationTree_Make_New_Then_Delete_App()
        {
            //create new app
            var appName = Guid.NewGuid().ToString("N");
            var treeName = Guid.NewGuid().ToString("N");
            Current.Services.SectionService.MakeNew(appName, appName, "icon.jpg");

            //check if it exists
            var app = Current.Services.SectionService.GetByAlias(appName);
            Assert.IsNotNull(app);

            //create the new app tree assigned to the new app
            Current.Services.ApplicationTreeService.MakeNew(false, 0, app.Alias, treeName, treeName, "icon.jpg", "icon.jpg", "Umbraco.Web.Trees.ContentTreeController, Umbraco.Web");
            var tree = Current.Services.ApplicationTreeService.GetByAlias(treeName);
            Assert.IsNotNull(tree);

            //now delete the app
            Current.Services.SectionService.DeleteSection(app);

            //check that the tree is gone
            Assert.AreEqual(0, Current.Services.ApplicationTreeService.GetApplicationTrees(treeName).Count());
        }

        #region Tests to write
        /////
        /////A test for ApplicationTree Constructor
        /////
        //[TestMethod()]
        //public void ApplicationTreeConstructorTest()
        //{
        //    bool silent = false; // TODO: Initialize to an appropriate value
        //    bool initialize = false; // TODO: Initialize to an appropriate value
        //    byte sortOrder = 0; // TODO: Initialize to an appropriate value
        //    string applicationAlias = string.Empty; // TODO: Initialize to an appropriate value
        //    string alias = string.Empty; // TODO: Initialize to an appropriate value
        //    string title = string.Empty; // TODO: Initialize to an appropriate value
        //    string iconClosed = string.Empty; // TODO: Initialize to an appropriate value
        //    string iconOpened = string.Empty; // TODO: Initialize to an appropriate value
        //    string assemblyName = string.Empty; // TODO: Initialize to an appropriate value
        //    string type = string.Empty; // TODO: Initialize to an appropriate value
        //    string action = string.Empty; // TODO: Initialize to an appropriate value
        //    ApplicationTree target = new ApplicationTree(silent, initialize, sortOrder, applicationAlias, alias, title, iconClosed, iconOpened, assemblyName, type, action);
        //    Assert.Inconclusive("TODO: Implement code to verify target");
        //}

        /////
        /////A test for ApplicationTree Constructor
        /////
        //[TestMethod()]
        //public void ApplicationTreeConstructorTest1()
        //{
        //    ApplicationTree target = new ApplicationTree();
        //    Assert.Inconclusive("TODO: Implement code to verify target");
        //}

        /////
        /////A test for Delete
        /////
        //[TestMethod()]
        //public void DeleteTest()
        //{
        //    ApplicationTree target = new ApplicationTree(); // TODO: Initialize to an appropriate value
        //    target.Delete();
        //    Assert.Inconclusive("A method that does not return a value cannot be verified.");
        //}

        /////
        /////A test for Save
        /////
        //[TestMethod()]
        //public void SaveTest()
        //{
        //    ApplicationTree target = new ApplicationTree(); // TODO: Initialize to an appropriate value
        //    target.Save();
        //    Assert.Inconclusive("A method that does not return a value cannot be verified.");
        //}

        /////
        /////A test for getAll
        /////
        //[TestMethod()]
        //public void getAllTest()
        //{
        //    ApplicationTree[] expected = null; // TODO: Initialize to an appropriate value
        //    ApplicationTree[] actual;
        //    actual = ApplicationTree.getAll();
        //    Assert.AreEqual(expected, actual);
        //    Assert.Inconclusive("Verify the correctness of this test method.");
        //}

        /////
        /////A test for getApplicationTree
        /////
        //[TestMethod()]
        //public void getApplicationTreeTest()
        //{
        //    string applicationAlias = string.Empty; // TODO: Initialize to an appropriate value
        //    ApplicationTree[] expected = null; // TODO: Initialize to an appropriate value
        //    ApplicationTree[] actual;
        //    actual = ApplicationTree.getApplicationTree(applicationAlias);
        //    Assert.AreEqual(expected, actual);
        //    Assert.Inconclusive("Verify the correctness of this test method.");
        //}

        /////
        /////A test for getApplicationTree
        /////
        //[TestMethod()]
        //public void getApplicationTreeTest1()
        //{
        //    string applicationAlias = string.Empty; // TODO: Initialize to an appropriate value
        //    bool onlyInitializedApplications = false; // TODO: Initialize to an appropriate value
        //    ApplicationTree[] expected = null; // TODO: Initialize to an appropriate value
        //    ApplicationTree[] actual;
        //    actual = ApplicationTree.getApplicationTree(applicationAlias, onlyInitializedApplications);
        //    Assert.AreEqual(expected, actual);
        //    Assert.Inconclusive("Verify the correctness of this test method.");
        //}

        /////
        /////A test for getByAlias
        /////
        //[TestMethod()]
        //public void getByAliasTest()
        //{
        //    string treeAlias = string.Empty; // TODO: Initialize to an appropriate value
        //    ApplicationTree expected = null; // TODO: Initialize to an appropriate value
        //    ApplicationTree actual;
        //    actual = ApplicationTree.getByAlias(treeAlias);
        //    Assert.AreEqual(expected, actual);
        //    Assert.Inconclusive("Verify the correctness of this test method.");
        //}

        /////
        /////A test for Action
        /////
        //[TestMethod()]
        //public void ActionTest()
        //{
        //    ApplicationTree target = new ApplicationTree(); // TODO: Initialize to an appropriate value
        //    string expected = string.Empty; // TODO: Initialize to an appropriate value
        //    string actual;
        //    target.Action = expected;
        //    actual = target.Action;
        //    Assert.AreEqual(expected, actual);
        //    Assert.Inconclusive("Verify the correctness of this test method.");
        //}

        /////
        /////A test for Alias
        /////
        //[TestMethod()]
        //public void AliasTest()
        //{
        //    ApplicationTree target = new ApplicationTree(); // TODO: Initialize to an appropriate value
        //    string actual;
        //    actual = target.Alias;
        //    Assert.Inconclusive("Verify the correctness of this test method.");
        //}

        /////
        /////A test for ApplicationAlias
        /////
        //[TestMethod()]
        //public void ApplicationAliasTest()
        //{
        //    ApplicationTree target = new ApplicationTree(); // TODO: Initialize to an appropriate value
        //    string actual;
        //    actual = target.ApplicationAlias;
        //    Assert.Inconclusive("Verify the correctness of this test method.");
        //}

        /////
        /////A test for AssemblyName
        /////
        //[TestMethod()]
        //public void AssemblyNameTest()
        //{
        //    ApplicationTree target = new ApplicationTree(); // TODO: Initialize to an appropriate value
        //    string expected = string.Empty; // TODO: Initialize to an appropriate value
        //    string actual;
        //    target.AssemblyName = expected;
        //    actual = target.AssemblyName;
        //    Assert.AreEqual(expected, actual);
        //    Assert.Inconclusive("Verify the correctness of this test method.");
        //}

        /////
        /////A test for IconClosed
        /////
        //[TestMethod()]
        //public void IconClosedTest()
        //{
        //    ApplicationTree target = new ApplicationTree(); // TODO: Initialize to an appropriate value
        //    string expected = string.Empty; // TODO: Initialize to an appropriate value
        //    string actual;
        //    target.IconClosed = expected;
        //    actual = target.IconClosed;
        //    Assert.AreEqual(expected, actual);
        //    Assert.Inconclusive("Verify the correctness of this test method.");
        //}

        /////
        /////A test for IconOpened
        /////
        //[TestMethod()]
        //public void IconOpenedTest()
        //{
        //    ApplicationTree target = new ApplicationTree(); // TODO: Initialize to an appropriate value
        //    string expected = string.Empty; // TODO: Initialize to an appropriate value
        //    string actual;
        //    target.IconOpened = expected;
        //    actual = target.IconOpened;
        //    Assert.AreEqual(expected, actual);
        //    Assert.Inconclusive("Verify the correctness of this test method.");
        //}

        /////
        /////A test for Initialize
        /////
        //[TestMethod()]
        //public void InitializeTest()
        //{
        //    ApplicationTree target = new ApplicationTree(); // TODO: Initialize to an appropriate value
        //    bool expected = false; // TODO: Initialize to an appropriate value
        //    bool actual;
        //    target.Initialize = expected;
        //    actual = target.Initialize;
        //    Assert.AreEqual(expected, actual);
        //    Assert.Inconclusive("Verify the correctness of this test method.");
        //}

        /////
        /////A test for Silent
        /////
        //[TestMethod()]
        //public void SilentTest()
        //{
        //    ApplicationTree target = new ApplicationTree(); // TODO: Initialize to an appropriate value
        //    bool expected = false; // TODO: Initialize to an appropriate value
        //    bool actual;
        //    target.Silent = expected;
        //    actual = target.Silent;
        //    Assert.AreEqual(expected, actual);
        //    Assert.Inconclusive("Verify the correctness of this test method.");
        //}

        /////
        /////A test for SortOrder
        /////
        //[TestMethod()]
        //public void SortOrderTest()
        //{
        //    ApplicationTree target = new ApplicationTree(); // TODO: Initialize to an appropriate value
        //    byte expected = 0; // TODO: Initialize to an appropriate value
        //    byte actual;
        //    target.SortOrder = expected;
        //    actual = target.SortOrder;
        //    Assert.AreEqual(expected, actual);
        //    Assert.Inconclusive("Verify the correctness of this test method.");
        //}

        /////
        /////A test for SqlHelper
        /////
        //[TestMethod()]
        //public void SqlHelperTest()
        //{
        //    ISqlHelper actual;
        //    actual = ApplicationTree.SqlHelper;
        //    Assert.Inconclusive("Verify the correctness of this test method.");
        //}

        /////
        /////A test for Title
        /////
        //[TestMethod()]
        //public void TitleTest()
        //{
        //    ApplicationTree target = new ApplicationTree(); // TODO: Initialize to an appropriate value
        //    string expected = string.Empty; // TODO: Initialize to an appropriate value
        //    string actual;
        //    target.Title = expected;
        //    actual = target.Title;
        //    Assert.AreEqual(expected, actual);
        //    Assert.Inconclusive("Verify the correctness of this test method.");
        //}

        /////
        /////A test for Type
        /////
        //[TestMethod()]
        //public void TypeTest()
        //{
        //    ApplicationTree target = new ApplicationTree(); // TODO: Initialize to an appropriate value
        //    string expected = string.Empty; // TODO: Initialize to an appropriate value
        //    string actual;
        //    target.Type = expected;
        //    actual = target.Type;
        //    Assert.AreEqual(expected, actual);
        //    Assert.Inconclusive("Verify the correctness of this test method.");
        //}
        #endregion

        #region Additional test attributes
        //
        //You can use the following additional attributes as you write your tests:
        //
        //Use ClassInitialize to run code before running the first test in the class
        //[ClassInitialize()]
        //public static void MyClassInitialize(TestContext testContext)
        //{
        //}
        //
        //Use ClassCleanup to run code after all tests in a class have run
        //[ClassCleanup()]
        //public static void MyClassCleanup()
        //{
        //}
        //
        //Use TestInitialize to run code before running each test
        //[TestInitialize()]
        //public void MyTestInitialize()
        //{
        //}
        //
        //Use TestCleanup to run code after each test has run
        //[TestCleanup()]
        //public void MyTestCleanup()
        //{
        //}
        //
        #endregion
    }
}