#!/bin/bash
import doc2tosca as d2t
import example as exp

def test_match_definition_incipit():
    assert d2t.match_definition_incipit("tosca.")
    assert d2t.match_definition_incipit("tosca.definitions")
    assert not d2t.match_definition_incipit("<node_template>")

def test_parse_versione_from_filename():
    '''
    Test parsing version out of filenames
    '''
    assert d2t.parse_version_from_filename("gs_NFV-SOL001v020601p.docx") == "v2.6.1"
    assert d2t.parse_version_from_filename("gs_nfv-sol001v020801p.docx") == "v2.8.1"

def test_is_lvl1_section_hdn():
    
    assert d2t.is_lvl1_section_hdn("6\tVNFD TOSCA model")
    assert d2t.is_lvl1_section_hdn("Annex A (informative)")
    assert d2t.is_lvl1_section_hdn("Annex C (normative):\tConformance\t284")

def test_is_lvl2_section_hdn():
    
    assert d2t.is_lvl2_section_hdn("6.3\tData Types")
    assert not d2t.is_lvl2_section_hdn("6.4.2\tSomething")
    assert not d2t.is_lvl2_section_hdn("6.4\tSomething")

def test_section_init():

    ssss = d2t.Section(0, 10, "6\tVNFD TOSCA model")
    assert ssss.number == 6
    assert ssss.title == "VNFD TOSCA model"
    assert not ssss.is_annex

    aaaa = d2t.Section(11, 20, "Annex A (informative): My title")
    assert aaaa.is_annex
    assert aaaa.title == "My title"
    assert aaaa.letter == "A"

def test_is_example_start():
    assert exp.is_start_of_example("tosca_definitions_version: tosca_simple_yaml_1_1")


txt = '''
The contents of MyExampleNs_Type.yaml file with the node type definition are as follows:
tosca_definitions_version: tosca_simple_yaml_1_2
 
description: type definition of tosca.MyExampleNS
 
imports:
  - etsi_nfv_sol001_nsd_types.yaml  # all of TOSCA types as defined in ETSI GS NFVSOL 001
 
node_types:
  tosca.MyExampleNS:
    derived_from: tosca.nodes.nfv.NS
    properties:
      descriptor_id:
        type: string
        constraints: [ valid_values: [ b1bb0ce7-ebca-4fa7-95ed-4840d70a1177 ] ]
        default: b1bb0ce7-ebca-4fa7-95ed-4840d70a1177
      designer:
        type: string
        constraints: [ valid_values: [ MyCompany] ]
        default: MyCompany
      name:
        type: string
        constraints: [ valid_values: [ ExampleService ] ]
        default: ExampleService
      version:
        type: string
        constraints: [ valid_values: [ '1.0' ] ]
        default: '1.0'
      invariant_id:
        type: string
        constraints: [ valid_values: [ 1111-2222-aaaa-bbbb ] ]
        default: 1111-2222-aaaa-bbbb
      flavour_id: 
        type: string
        constraints: [ valid_values: [ small, big ] ]
        default: small
    requirements:
      - virtual_link:
          capability: tosca.capabilities.nfv.VirtualLinkable
    interfaces:
      Nslcm:
        type: tosca.interfaces.nfv.Nslcm

The following snippet shows the service template representing the NSD NS_2. In this example, NS_2 supports one single deployment flavour.
MyExampleNS_2.yaml:
tosca_definitions_version: tosca_simple_yaml_1_1

description: Relational database, simple

imports:
  - etsi_nfv_sol001_nsd_types.yaml  # all of NSD related TOSCA types as defined in ETSI GS NFV-SOL 001
  - example_VNF3.yaml # uri of the yaml file which contains the definition of tosca.nodes.nfv.example_VNF3, this file might be included in the NSD file structure
  - example_VNF4.yaml # uri of the yaml file which contains the definition of tosca.nodes.nfv.example_VNF4, this file might be included in the NSD file structure

node_types:
  tosca.myExample.NS_2:
    derived_from: tosca.nodes.nfv.NS
    properties:
      descriptor_id:
        type: string
        constraints: [ valid_values: [ c1bb0ab8-deab-4fa7-95ed-4840d70a3574 ] ]
        default: c1bb0ab8-deab-4fa7-95ed-4840d70a3574
      designer:
        type: string
        constraints: [ valid_values: [ MyCompany] ]
        default: MyCompany
      name:
        type: string
        constraints: [ valid_values: [ myExample2Service ] ]
        default: myExample2Service
      version:
        type: string
        constraints: [ valid_values: [ '1.0.0.0' ] ]
        default: '1.0.0.0'
      invariant_id:
        type: string
        constraints: [ valid_values: [ aaaa-bbbb-cccc-dddd ] ]
        default: aaaa-bbbb-cccc-dddd
      flavour_id: 
        type: string
        constraints: [ valid_values: [ simple ] ]
        default: simple
    
topology_template:
  substitution_mappings:
    node_type: tosca.myExample.NS_2
    requirements:
      virtual_link: [ VNF_4, virtual_link_2 ] # the External connection point of 
                                              # VNF_2 is exposed as the Sap

   node_templates:
    NS_2:
      type: tosca.myExample.NS_2
      interfaces:
        Nslcm:
          instantiate:
            implementation: instantiate.workflow.yaml
          terminate:
            implementation: terminate.workflow.yaml

    VNF_3:
      type: tosca.nodes.nfv.example_VNF3
      properties:
        # no property assignments needed for required properties that have a default value assigned in the node type definition, e.g. descriptor_id
        flavour_id: simple
        vnf_profile:
          instantiation_level: level_1
          min_number_of_instances: 2
          max_number_of_instances: 6
      requirements:
        - virtual_link: NS_VL_2
    
    VNF_4:
      type: tosca.nodes.nfv.example_VNF4
      properties:
        flavour_id: simple
        vnf_profile:
          instantiation_level: level_1
          min_number_of_instances: 1
          max_number_of_instances: 3
      requirements:
        - virtual_link_1: NS_VL_2
        # - virtual_link_2: # map to virtual_link requirement of the NS node

    NS_VL_2:
      type: tosca.nodes.nfv.NsVirtualLink
      properties:
        connectivity_type:
          layer_protocols: [ipv4]
          flow_pattern: mesh
        vl_profile:
          max_bitrate_requirements:
             root: 1000
          min_bitrate_requirements:    
             root: 1000
  

Arial A.13   Virtual IP address connection point
Virtual IP address connection points (VipCps) are used to allocate one or multiple IP addresses that are shared by other CP instances, which may be instances of the same or of different VduCp or VnfExtCp nodes.
Load balancing
'''

txt_short = '''
The contents of MyExampleNs_Type.yaml file with the node type definition are as follows:
tosca_definitions_version: tosca_simple_yaml_1_2
 
description: type definition of tosca.MyExampleNS
 
imports:
  - etsi_nfv_sol001_nsd_types.yaml  # all of TOSCA types as defined in ETSI GS NFVSOL 001
 
node_types:
  tosca.MyExampleNS:
    derived_from: tosca.nodes.nfv.NS
    properties:
      descriptor_id:
        type: string
        constraints: [ valid_values: [ b1bb0ce7-ebca-4fa7-95ed-4840d70a1177 ] ]
        default: b1bb0ce7-ebca-4fa7-95ed-4840d70a1177
      designer:
        type: string
        constraints: [ valid_values: [ MyCompany] ]
        default: MyCompany

The following snippet shows the service template representing the NSD NS_2. In this example, NS_2 supports one single deployment flavour.
MyExampleNS_2.yaml:
tosca_definitions_version: tosca_simple_yaml_1_1

description: Relational database, simple

imports:
  - etsi_nfv_sol001_nsd_types.yaml  # all of NSD related TOSCA types as defined in ETSI GS NFV-SOL 001

node_types:
  tosca.myExample.NS_2:
    derived_from: tosca.nodes.nfv.NS
    properties:
      descriptor_id:
        type: string
        constraints: [ valid_values: [ c1bb0ab8-deab-4fa7-95ed-4840d70a3574 ] ]
        default: c1bb0ab8-deab-4fa7-95ed-4840d70a3574
    
topology_template:
  substitution_mappings:
    node_type: tosca.myExample.NS_2
    requirements:
      virtual_link: [ VNF_4, virtual_link_2 ] # the External connection point of 
                                              # VNF_2 is exposed as the Sap
    
    VNF_4:
      type: tosca.nodes.nfv.example_VNF4
      properties:
        flavour_id: simple
        vnf_profile:
          instantiation_level: level_1
          min_number_of_instances: 1
          max_number_of_instances: 3
      requirements:
        - virtual_link_1: NS_VL_2
        # - virtual_link_2: # map to virtual_link requirement of the NS node
  

Arial A.13   Virtual IP address connection point
Virtual IP address connection points (VipCps) are used to allocate one or multiple IP addresses that are shared by other CP instances, which may be instances of the same or of different VduCp or VnfExtCp nodes.
Load balancing
'''

sunshine = '''
sunshineVNF.yaml
tosca_definitions_version: tosca_simple_yaml_1_3

description: Relational database, non-scalable

imports:
  - etsi_nfv_sol001_vnfd_types.yaml  # all of TOSCA VNFD types as defined in ETSI GS NFV-SOL 001

data_types:
  MyCompany.datatypes.nfv.VnfInstantiateAdditionalParameters:
    derived_from: tosca.datatypes.nfv.VnfOperationAdditionalParameters
    properties:
      parameter_1:
        type: string
        required: true
        default: value_1
      parameter_2:
        type: string
        required: true
        default: value_2

node_types:
  MyCompany.SunshineDB.1_0.1_0:
    derived_from: tosca.nodes.nfv.VNF
    properties:
      descriptor_id:
        type: string
        constraints: [ equal: b1bb0ce7-ebca-4fa7-95ed-4840d70a1177 ]
        default: b1bb0ce7-ebca-4fa7-95ed-4840d70a1177
      provider:
        type: string
        constraints: [ equal: MyCompany ]
        default: MyCompany
      product_name:
        type: string
        constraints: [ equal: SunshineDB ]
        default: SunshineDB
      software_version:
        type: string
        constraints: [ equal: '1.0' ]
        default: '1.0'
      descriptor_version:
        type: string
        constraints: [ equal: '1.0' ]
        default: '1.0'
      flavour_id: 
        type: string
        constraints: [ valid_values: [ simple, complex ] ]
        default: simple
      flavour_description: 
        type: string
        default: "" #empty string 
      vnfm_info:
        type: list
        entry_schema:
          type: string
          constraints: [ equal: '0:MyCompany-1.0.0' ]
        default: [ '0:MyCompany-1.0.0' ]
    requirements:
      - virtual_link:
          capability: tosca.capabilities.nfv.VirtualLinkable
          occurrences: [ 0, 0 ]
      - virtual_link_backend:
          capability: tosca.capabilities.nfv.VirtualLinkable
          occurrences: [ 0, 1 ]
      - virtual_link_service:
          capability: tosca.capabilities.nfv.VirtualLinkable
          occurrences: [ 0, 1 ]
    interfaces:
      Vnflcm:
        type: tosca.interfaces.nfv.Vnflcm
        operations:
          instantiate:
            inputs:
              additional_parameters:
                type: MyCompany.datatypes.nfv.VnfInstantiateAdditionalParameters
    

The vnf node template in the sunshine.vnfd.tosca.yaml file is abstract and is subject to substitution; the lower-level templates
'''

sunshine_vnfd = '''
SunshineDB: VNFD-top level
sunshine.vnfd.tosca.yaml 
tosca_definitions_version: tosca_simple_yaml_1_3

description: Relational database, non-scalable
imports:
  - etsi_nfv_sol001_vnfd_types.yaml  # all of TOSCA VNFD types as defined in ETSI GS NFV SOL 001
  - sunshineVNF.yaml # contains the VNF node type definition


topology_template:
  inputs:
    flavour_id:
      type: string
      description: VNF deployment flavour selected by the consumer. It is provided in the API       

  node_templates: 
    SunshineDB:
        type: MyCompany.SunshineDB.1_0.1_0
        properties:
          flavour_id: { get_input: flavour_id }
          descriptor_id: b1bb0ce7-ebca-4fa7-95ed-4840d70a1177
          provider: MyCompany
          product_name: SunshineDB
          software_version: '1.0'
          descriptor_version: '1.0'
          vnfm_info:
            - '0:MyCompany-1.0.0'
       # requirements:
          #- virtual_link_backend # mapped in lower-level templates
          #- virtual_link_service # mapped in lower-level templates
        # get_input function would be used to process the template at run time to access the selected flavour id. If the TOSCA functions are not supported by VNFM, the above function may not be needed, what other mechanisms can be used by VNFM which provide the same function are out of scope of the present document.

Something
'''

def test_parse_example_short():

    examples = exp.parse_all_examples(txt_short.split("\n"))
    assert len(examples) == 2
    assert len(examples[1].text.split("\n")) == 37 # MyExampleNS_2.yaml


def test_parse_example_long():

    examples = exp.parse_all_examples(txt.split("\n"))
    assert len(examples) == 2
    assert len(examples[1].text.split("\n")) == 93 # MyExampleNS_2.yaml

def test_parse_example_sunshine():

    examples = exp.parse_all_examples(sunshine.split("\n"))
    assert len(examples) == 1
    assert len(examples[0].text.split("\n")) == 78

def test_parse_example_sunshine_vnfd():

    examples = exp.parse_all_examples(sunshine_vnfd.split("\n"))
    assert len(examples) == 1
    assert len(examples[0].text.split("\n")) == 32


def test_get_example_file_name():

    line1 = """The following snippet shows the service template representing the NSD NS_2. In this example, NS_2 supports one single deployment flavour.
MyExampleNS_2.yaml:"""
    line2 = """The contents of MyExampleNs_Type.yaml file with the node type definition are as follows:"""
    line3 = """Virtual IP address connection points (VipCps) are used to allocate one or multiple IP addresses that are shared by other CP instances, which may be instances of the same or of different VduCp or VnfExtCp nodes."""


    assert exp.get_example_file_name(line1) == "MyExampleNS_2.yaml"
    assert exp.get_example_file_name(line2) == "MyExampleNs_Type.yaml"
    assert exp.get_example_file_name(line3) == ""

