package ca.queensu.cs.mase.urml.tests;

import ca.queensu.cs.mase.UrmlInjectorProvider;
import ca.queensu.cs.mase.urml.Attribute;
import ca.queensu.cs.mase.urml.Capsule;
import ca.queensu.cs.mase.urml.Model;
import ca.queensu.cs.mase.urml.NoOp;
import ca.queensu.cs.mase.urml.Operation;
import ca.queensu.cs.mase.urml.Port;
import ca.queensu.cs.mase.urml.Protocol;
import ca.queensu.cs.mase.urml.Signal;
import ca.queensu.cs.mase.urml.StatementOperation;
import ca.queensu.cs.mase.urml.UrmlPackage;
import ca.queensu.cs.mase.validation.UrmlValidator;
import com.google.inject.Inject;
import org.eclipse.emf.common.util.EList;
import org.eclipse.xtend2.lib.StringConcatenation;
import org.eclipse.xtext.junit4.InjectWith;
import org.eclipse.xtext.junit4.XtextRunner;
import org.eclipse.xtext.junit4.util.ParseHelper;
import org.eclipse.xtext.junit4.validation.ValidationTestHelper;
import org.eclipse.xtext.xbase.lib.Exceptions;
import org.eclipse.xtext.xbase.lib.Extension;
import org.junit.Assert;
import org.junit.Test;
import org.junit.runner.RunWith;

@RunWith(XtextRunner.class)
@InjectWith(UrmlInjectorProvider.class)
@SuppressWarnings("all")
public class ModelBasicTest {
  @Inject
  @Extension
  private ParseHelper<Model> _parseHelper;
  
  @Inject
  @Extension
  private ValidationTestHelper _validationTestHelper;
  
  @Test
  public void testEmptyModel() {
    try {
      StringConcatenation _builder = new StringConcatenation();
      _builder.append("model emptyModel {}");
      _builder.newLine();
      final Model model = this._parseHelper.parse(_builder);
      Assert.assertEquals("emptyModel", model.getName());
      int _size = model.getProtocols().size();
      boolean _equals = (_size == 0);
      Assert.assertTrue(_equals);
      int _size_1 = model.getCapsules().size();
      boolean _equals_1 = (_size_1 == 0);
      Assert.assertTrue(_equals_1);
      this._validationTestHelper.assertError(model, UrmlPackage.eINSTANCE.getModel(), UrmlValidator.NO_ROOT);
    } catch (Throwable _e) {
      throw Exceptions.sneakyThrow(_e);
    }
  }
  
  @Test
  public void testCapsule() {
    try {
      StringConcatenation _builder = new StringConcatenation();
      _builder.append("model capsule1 {");
      _builder.newLine();
      _builder.append("\t");
      _builder.append("root capsule cap {}");
      _builder.newLine();
      _builder.append("}");
      final Model model = this._parseHelper.parse(_builder);
      Assert.assertEquals("capsule1", model.getName());
      int _size = model.getProtocols().size();
      boolean _equals = (_size == 0);
      Assert.assertTrue(_equals);
      int _size_1 = model.getCapsules().size();
      boolean _equals_1 = (_size_1 == 1);
      Assert.assertTrue(_equals_1);
      final Capsule cap = model.getCapsules().get(0);
      Assert.assertEquals("cap", cap.getName());
      Assert.assertTrue(cap.isRoot());
      this._validationTestHelper.assertNoErrors(model);
    } catch (Throwable _e) {
      throw Exceptions.sneakyThrow(_e);
    }
  }
  
  @Test
  public void testCapsuleNoRoot() {
    try {
      StringConcatenation _builder = new StringConcatenation();
      _builder.append("model capsule1noRoot {");
      _builder.newLine();
      _builder.append("\t");
      _builder.append("capsule cap {}");
      _builder.newLine();
      _builder.append("}");
      final Model model = this._parseHelper.parse(_builder);
      this._validationTestHelper.assertError(model, UrmlPackage.eINSTANCE.getModel(), UrmlValidator.NO_ROOT);
    } catch (Throwable _e) {
      throw Exceptions.sneakyThrow(_e);
    }
  }
  
  @Test
  public void testProtocolEmpty() {
    try {
      StringConcatenation _builder = new StringConcatenation();
      _builder.append("model proto {");
      _builder.newLine();
      _builder.append("\t");
      _builder.append("root capsule cap{}");
      _builder.newLine();
      _builder.append("\t");
      _builder.append("protocol one {}");
      _builder.newLine();
      _builder.append("}");
      final Model model = this._parseHelper.parse(_builder);
      int _size = model.getProtocols().size();
      boolean _equals = (_size == 1);
      Assert.assertTrue(_equals);
      Assert.assertEquals("one", model.getProtocols().get(0).getName());
      this._validationTestHelper.assertNoErrors(model);
    } catch (Throwable _e) {
      throw Exceptions.sneakyThrow(_e);
    }
  }
  
  @Test
  public void testProtocolInOut() {
    try {
      StringConcatenation _builder = new StringConcatenation();
      _builder.append("model proto {");
      _builder.newLine();
      _builder.append("\t");
      _builder.append("root capsule cap {}");
      _builder.newLine();
      _builder.append("\t");
      _builder.append("protocol one {");
      _builder.newLine();
      _builder.append("\t\t");
      _builder.append("incoming {}");
      _builder.newLine();
      _builder.append("\t\t");
      _builder.append("outgoing {}");
      _builder.newLine();
      _builder.append("\t");
      _builder.append("}");
      _builder.newLine();
      _builder.append("}");
      final Model model = this._parseHelper.parse(_builder);
      this._validationTestHelper.assertNoErrors(model);
      int _size = model.getProtocols().size();
      boolean _equals = (_size == 1);
      Assert.assertTrue(_equals);
      int _size_1 = model.getProtocols().get(0).getIncomingMessages().size();
      boolean _equals_1 = (_size_1 == 0);
      Assert.assertTrue(_equals_1);
      int _size_2 = model.getProtocols().get(0).getOutgoingMessages().size();
      boolean _equals_2 = (_size_2 == 0);
      Assert.assertTrue(_equals_2);
    } catch (Throwable _e) {
      throw Exceptions.sneakyThrow(_e);
    }
  }
  
  @Test
  public void testProtocolSignal() {
    try {
      StringConcatenation _builder = new StringConcatenation();
      _builder.append("model protoSignal {");
      _builder.newLine();
      _builder.append("\t");
      _builder.append("root capsule cap {}");
      _builder.newLine();
      _builder.append("\t");
      _builder.append("protocol one {");
      _builder.newLine();
      _builder.append("\t\t");
      _builder.append("incoming {");
      _builder.newLine();
      _builder.append("\t\t\t");
      _builder.append("signal1()");
      _builder.newLine();
      _builder.append("\t\t");
      _builder.append("}");
      _builder.newLine();
      _builder.append("\t");
      _builder.append("}");
      _builder.newLine();
      _builder.append("}");
      final Model model = this._parseHelper.parse(_builder);
      this._validationTestHelper.assertNoErrors(model);
      int _size = model.getProtocols().size();
      boolean _equals = (_size == 1);
      Assert.assertTrue(_equals);
      final Protocol one = model.getProtocols().get(0);
      int _size_1 = one.getIncomingMessages().size();
      boolean _equals_1 = (_size_1 == 1);
      Assert.assertTrue(_equals_1);
      final Signal signal1 = one.getIncomingMessages().get(0);
      int _size_2 = signal1.getLocalVars().size();
      boolean _equals_2 = (_size_2 == 0);
      Assert.assertTrue(_equals_2);
      Assert.assertEquals("signal1", signal1.getName());
    } catch (Throwable _e) {
      throw Exceptions.sneakyThrow(_e);
    }
  }
  
  @Test
  public void testProtocolSignals() {
    try {
      StringConcatenation _builder = new StringConcatenation();
      _builder.append("model protoSignal {");
      _builder.newLine();
      _builder.append("\t");
      _builder.append("root capsule cap {}");
      _builder.newLine();
      _builder.append("\t");
      _builder.append("protocol one {");
      _builder.newLine();
      _builder.append("\t\t");
      _builder.append("incoming {");
      _builder.newLine();
      _builder.append("\t\t\t");
      _builder.append("signal1()");
      _builder.newLine();
      _builder.append("\t\t\t");
      _builder.append("signal2()");
      _builder.newLine();
      _builder.append("\t\t");
      _builder.append("}");
      _builder.newLine();
      _builder.append("\t");
      _builder.append("}");
      _builder.newLine();
      _builder.append("}");
      final Model model = this._parseHelper.parse(_builder);
      this._validationTestHelper.assertNoErrors(model);
      int _size = model.getProtocols().size();
      boolean _equals = (_size == 1);
      Assert.assertTrue(_equals);
      final Protocol one = model.getProtocols().get(0);
      int _size_1 = one.getIncomingMessages().size();
      boolean _equals_1 = (_size_1 == 2);
      Assert.assertTrue(_equals_1);
      final Signal signal1 = one.getIncomingMessages().get(0);
      final Signal signal2 = one.getIncomingMessages().get(1);
      int _size_2 = signal1.getLocalVars().size();
      boolean _equals_2 = (_size_2 == 0);
      Assert.assertTrue(_equals_2);
      Assert.assertEquals("signal1", signal1.getName());
      int _size_3 = signal2.getLocalVars().size();
      boolean _equals_3 = (_size_3 == 0);
      Assert.assertTrue(_equals_3);
      Assert.assertEquals("signal2", signal2.getName());
    } catch (Throwable _e) {
      throw Exceptions.sneakyThrow(_e);
    }
  }
  
  @Test
  public void testProtocolSignalParam() {
    try {
      StringConcatenation _builder = new StringConcatenation();
      _builder.append("model protoSignalParam {");
      _builder.newLine();
      _builder.append("\t");
      _builder.append("root capsule cap {}");
      _builder.newLine();
      _builder.append("\t");
      _builder.append("protocol one {");
      _builder.newLine();
      _builder.append("\t\t");
      _builder.append("incoming {");
      _builder.newLine();
      _builder.append("\t\t\t");
      _builder.append("signal1(a)");
      _builder.newLine();
      _builder.append("\t\t");
      _builder.append("}");
      _builder.newLine();
      _builder.append("\t");
      _builder.append("}");
      _builder.newLine();
      _builder.append("}");
      final Model model = this._parseHelper.parse(_builder);
      this._validationTestHelper.assertNoErrors(model);
      final Signal one = model.getProtocols().get(0).getIncomingMessages().get(0);
      int _size = one.getLocalVars().size();
      boolean _equals = (_size == 1);
      Assert.assertTrue(_equals);
      Assert.assertEquals("a", one.getLocalVars().get(0).getName());
    } catch (Throwable _e) {
      throw Exceptions.sneakyThrow(_e);
    }
  }
  
  @Test
  public void testProtocolSignalParams() {
    try {
      StringConcatenation _builder = new StringConcatenation();
      _builder.append("model protoSignalParam {");
      _builder.newLine();
      _builder.append("\t");
      _builder.append("root capsule cap {}");
      _builder.newLine();
      _builder.append("\t");
      _builder.append("protocol one {");
      _builder.newLine();
      _builder.append("\t\t");
      _builder.append("incoming {");
      _builder.newLine();
      _builder.append("\t\t\t");
      _builder.append("signal1(a,b)");
      _builder.newLine();
      _builder.append("\t\t");
      _builder.append("}");
      _builder.newLine();
      _builder.append("\t");
      _builder.append("}");
      _builder.newLine();
      _builder.append("}");
      final Model model = this._parseHelper.parse(_builder);
      this._validationTestHelper.assertNoErrors(model);
      final Signal one = model.getProtocols().get(0).getIncomingMessages().get(0);
      int _size = one.getLocalVars().size();
      boolean _equals = (_size == 2);
      Assert.assertTrue(_equals);
      Assert.assertEquals("a", one.getLocalVars().get(0).getName());
      Assert.assertEquals("b", one.getLocalVars().get(1).getName());
    } catch (Throwable _e) {
      throw Exceptions.sneakyThrow(_e);
    }
  }
  
  public void testCapsuleAttribute() {
    try {
      StringConcatenation _builder = new StringConcatenation();
      _builder.append("model capAttrib {");
      _builder.newLine();
      _builder.append("\t");
      _builder.append("root capsule cap {");
      _builder.newLine();
      _builder.append("\t\t");
      _builder.append("attribute a");
      _builder.newLine();
      _builder.append("\t");
      _builder.append("}");
      _builder.newLine();
      _builder.append("}");
      final Model model = this._parseHelper.parse(_builder);
      this._validationTestHelper.assertNoErrors(model);
      final EList<Attribute> attribs = model.getCapsules().get(0).getAttributes();
      int _size = attribs.size();
      boolean _equals = (_size == 1);
      Assert.assertTrue(_equals);
      Assert.assertEquals(attribs.get(0).getName(), "a");
    } catch (Throwable _e) {
      throw Exceptions.sneakyThrow(_e);
    }
  }
  
  @Test
  public void testCapsuleRootExternalPort() {
    try {
      StringConcatenation _builder = new StringConcatenation();
      _builder.append("model test {");
      _builder.newLine();
      _builder.append("\t");
      _builder.append("root capsule cap {");
      _builder.newLine();
      _builder.append("\t\t");
      _builder.append("external port Port1 : One");
      _builder.newLine();
      _builder.append("\t");
      _builder.append("}");
      _builder.newLine();
      _builder.append("\t");
      _builder.append("protocol One {}");
      _builder.newLine();
      _builder.append("}");
      final Model model = this._parseHelper.parse(_builder);
      this._validationTestHelper.assertError(model, UrmlPackage.eINSTANCE.getCapsule(), UrmlValidator.ROOT_EXTERN_PORT);
      int _size = model.getCapsules().get(0).getInterfacePorts().size();
      boolean _equals = (_size == 1);
      Assert.assertTrue(_equals);
      Assert.assertEquals(model.getCapsules().get(0).getInterfacePorts().get(0).getName(), "Port1");
    } catch (Throwable _e) {
      throw Exceptions.sneakyThrow(_e);
    }
  }
  
  @Test
  public void testCapsuleNonRootExternalPort() {
    try {
      StringConcatenation _builder = new StringConcatenation();
      _builder.append("model test {");
      _builder.newLine();
      _builder.append("\t");
      _builder.append("root capsule rootCap {}");
      _builder.newLine();
      _builder.append("\t");
      _builder.append("capsule cap {");
      _builder.newLine();
      _builder.append("\t\t");
      _builder.append("external port Port1: One");
      _builder.newLine();
      _builder.append("\t");
      _builder.append("}");
      _builder.newLine();
      _builder.append("\t");
      _builder.append("protocol One {}");
      _builder.newLine();
      _builder.append("}");
      final Model model = this._parseHelper.parse(_builder);
      this._validationTestHelper.assertNoErrors(model);
      final EList<Port> extPorts = model.getCapsules().get(1).getInterfacePorts();
      int _size = extPorts.size();
      boolean _equals = (_size == 1);
      Assert.assertTrue(_equals);
      Assert.assertEquals(extPorts.get(0).getName(), "Port1");
      Assert.assertEquals(extPorts.get(0).getProtocol().getName(), "One");
    } catch (Throwable _e) {
      throw Exceptions.sneakyThrow(_e);
    }
  }
  
  @Test
  public void testCapsuleInternalPort() {
    try {
      StringConcatenation _builder = new StringConcatenation();
      _builder.append("model test {");
      _builder.newLine();
      _builder.append("\t");
      _builder.append("root capsule rootCap {");
      _builder.newLine();
      _builder.append("\t\t");
      _builder.append("port InPort1: One");
      _builder.newLine();
      _builder.append("\t");
      _builder.append("}");
      _builder.newLine();
      _builder.append("\t");
      _builder.append("protocol One {}");
      _builder.newLine();
      _builder.append("}");
      final Model model = this._parseHelper.parse(_builder);
      this._validationTestHelper.assertNoErrors(model);
      final EList<Port> intPorts = model.getCapsules().get(0).getInternalPorts();
      int _size = intPorts.size();
      boolean _equals = (_size == 1);
      Assert.assertTrue(_equals);
      Assert.assertEquals(intPorts.get(0).getName(), "InPort1");
      Assert.assertEquals(intPorts.get(0).getProtocol().getName(), "One");
    } catch (Throwable _e) {
      throw Exceptions.sneakyThrow(_e);
    }
  }
  
  @Test
  public void testCapsuleTimerPort() {
    try {
      StringConcatenation _builder = new StringConcatenation();
      _builder.append("model test {");
      _builder.newLine();
      _builder.append("\t");
      _builder.append("root capsule cap {");
      _builder.newLine();
      _builder.append("\t\t");
      _builder.append("timerPort tp");
      _builder.newLine();
      _builder.append("\t");
      _builder.append("}");
      _builder.newLine();
      _builder.append("}");
      final Model model = this._parseHelper.parse(_builder);
      this._validationTestHelper.assertNoErrors(model);
      Assert.assertEquals(model.getCapsules().get(0).getTimerPorts().get(0).getName(), "tp");
    } catch (Throwable _e) {
      throw Exceptions.sneakyThrow(_e);
    }
  }
  
  @Test
  public void testCapsuleLogPort() {
    try {
      StringConcatenation _builder = new StringConcatenation();
      _builder.append("model test {");
      _builder.newLine();
      _builder.append("\t");
      _builder.append("root capsule cap {");
      _builder.newLine();
      _builder.append("\t\t");
      _builder.append("logPort lp");
      _builder.newLine();
      _builder.append("\t");
      _builder.append("}");
      _builder.newLine();
      _builder.append("}");
      final Model model = this._parseHelper.parse(_builder);
      this._validationTestHelper.assertNoErrors(model);
      Assert.assertEquals(model.getCapsules().get(0).getLogPorts().get(0).getName(), "lp");
    } catch (Throwable _e) {
      throw Exceptions.sneakyThrow(_e);
    }
  }
  
  @Test
  public void testCapsuleRef() {
    try {
      StringConcatenation _builder = new StringConcatenation();
      _builder.append("model test {");
      _builder.newLine();
      _builder.append("\t");
      _builder.append("root capsule cap {");
      _builder.newLine();
      _builder.append("\t\t");
      _builder.append("capsuleRef cr: a");
      _builder.newLine();
      _builder.append("\t");
      _builder.append("}");
      _builder.newLine();
      _builder.append("\t");
      _builder.newLine();
      _builder.append("\t");
      _builder.append("capsule a {}");
      _builder.newLine();
      _builder.append("}");
      final Model model = this._parseHelper.parse(_builder);
      this._validationTestHelper.assertNoErrors(model);
      Assert.assertEquals(model.getCapsules().get(0).getCapsuleInsts().get(0).getName(), "cr");
      Assert.assertEquals(model.getCapsules().get(0).getCapsuleInsts().get(0).getType(), 
        model.getCapsules().get(1));
    } catch (Throwable _e) {
      throw Exceptions.sneakyThrow(_e);
    }
  }
  
  @Test
  public void testCapsuleConnector() {
    try {
      StringConcatenation _builder = new StringConcatenation();
      _builder.append("model test {");
      _builder.newLine();
      _builder.append("\t");
      _builder.append("root capsule cap {");
      _builder.newLine();
      _builder.append("\t\t");
      _builder.append("capsuleRef aRef: a");
      _builder.newLine();
      _builder.append("\t\t");
      _builder.append("capsuleRef bRef: b");
      _builder.newLine();
      _builder.append("\t\t");
      _builder.append("connector aRef.one and bRef.two");
      _builder.newLine();
      _builder.append("\t");
      _builder.append("}");
      _builder.newLine();
      _builder.append("\t");
      _builder.append("capsule a { external port one: alpha }");
      _builder.newLine();
      _builder.append("\t");
      _builder.append("capsule b { external port two: alpha }");
      _builder.newLine();
      _builder.append("\t");
      _builder.append("protocol alpha {}");
      _builder.newLine();
      _builder.append("}");
      final Model model = this._parseHelper.parse(_builder);
      this._validationTestHelper.assertNoErrors(model);
      Assert.assertEquals(model.getCapsules().get(0).getConnectors().get(0).getPort1(), 
        model.getCapsules().get(1).getInterfacePorts().get(0));
      Assert.assertEquals(model.getCapsules().get(0).getConnectors().get(0).getPort2(), 
        model.getCapsules().get(2).getInterfacePorts().get(0));
    } catch (Throwable _e) {
      throw Exceptions.sneakyThrow(_e);
    }
  }
  
  @Test
  public void testCapsuleOperation() {
    try {
      StringConcatenation _builder = new StringConcatenation();
      _builder.append("model test {");
      _builder.newLine();
      _builder.append("\t");
      _builder.append("root capsule cap {");
      _builder.newLine();
      _builder.append("\t\t");
      _builder.append("operation oper() {");
      _builder.newLine();
      _builder.append("\t\t\t");
      _builder.append("noop");
      _builder.newLine();
      _builder.append("\t\t");
      _builder.append("}");
      _builder.newLine();
      _builder.append("\t");
      _builder.append("}");
      _builder.newLine();
      _builder.append("}");
      final Model model = this._parseHelper.parse(_builder);
      this._validationTestHelper.assertNoErrors(model);
      final Operation oper = model.getCapsules().get(0).getOperations().get(0);
      Assert.assertEquals(oper.getName(), "oper");
      Assert.assertEquals(oper.getLocalVars().size(), 0);
      final StatementOperation noop = oper.getOperationCode().getStatements().get(0);
      Assert.assertTrue((noop instanceof NoOp));
    } catch (Throwable _e) {
      throw Exceptions.sneakyThrow(_e);
    }
  }
  
  @Test
  public void testCapsuleSMachine() {
    StringConcatenation _builder = new StringConcatenation();
    _builder.append("model test {");
    _builder.newLine();
    _builder.append("\t");
    _builder.append("root capsule cap {");
    _builder.newLine();
    _builder.append("\t\t");
    _builder.append("state");
    _builder.newLine();
    _builder.append("}");
    final String model = _builder.toString();
  }
}
