calabelm.gms : Test Connect agent LabelManipulator

Description

This test ensures the correctness of the Connect agent LabelManipulator.

Contributor: Ahmed Alqershi, June 2023


Small Model of Type : GAMS


Category : GAMS Test library


Main file : calabelm.gms

$title 'Test Connect agent LabelManipulator' (CALABELM,SEQ=942)
$ontext
This test ensures the correctness of the Connect agent LabelManipulator.

Contributor: Ahmed Alqershi, June 2023
$offtext


$log --- Using Python library %sysEnv.GMSPYTHONLIB%


Set i(*) canning plants /
'seattle',
'san-diego' /;

Set j(*) markets /
'new-york',
'chicago',
'topeka'    /;

Parameter a(i) capacity of plant i in cases /
'seattle' 350,
'san-diego' 600 /;

Parameter b(j) demand at market j in cases /
'new-york' 325,
'chicago' 300,
'topeka' 275 /;

Parameter d(i,j) distance in thousands of miles /
'seattle'.'new-york' 2.5,
'seattle'.'chicago' 1.7,
'seattle'.'topeka' 1.8,
'san-diego'.'new-york' 2.5,
'san-diego'.'chicago' 1.8,
'san-diego'.'topeka' 1.4 /;

Scalar f freight in dollars per case per thousand miles / 90 /;

Parameter c(i,j) transport cost in thousands of dollars per case /
'seattle'.'new-york' 0.225,
'seattle'.'chicago' 0.153,
'seattle'.'topeka' 0.162,
'san-diego'.'new-york' 0.225,
'san-diego'.'chicago' 0.162,
'san-diego'.'topeka' 0.126 /;

positive Variable x(i,j) shipment quantities in cases /
'seattle'.'new-york'.L 50,
'seattle'.'chicago'.L 300,
'seattle'.'topeka'.M 0.036,
'san-diego'.'new-york'.L 275,
'san-diego'.'chicago'.M 0.009,
'san-diego'.'topeka'.L 275 /;

free Variable z total transportation costs in thousands of dollars /L 153.675 /;

Equation cost define objective function /M 1, LO 0, UP 0 /;

Equation supply(i) observe supply limit at plant i /
'seattle'.L 350,
'seattle'.M Eps,
'seattle'.LO -Inf,
'seattle'.UP 350,
'san-diego'.L 550,
'san-diego'.LO -Inf,
'san-diego'.UP 600 /;

Equation demand(j) satisfy demand at market j /
'new-york'.L 325,
'new-york'.M 0.225,
'new-york'.LO 325,
'new-york'.UP +Inf,
'chicago'.L 300,
'chicago'.M 0.153,
'chicago'.LO 300,
'chicago'.UP +Inf,
'topeka'.L 275,
'topeka'.M 0.126,
'topeka'.LO 275,
'topeka'.UP +Inf /;

Set mapping_set(*) map labels / seattle  'Braunschweig' , chicago 'Hannover' /  ;
Set inv_mapping_set(*) map labels / Braunschweig  'seattle' , Hannover 'chicago' /  ;
Set regex_save(*) 'Set to save regex manipulations' / / ;
Set code_save(*) 'Set to save regex manipulations' / / ;


$log ### test expected errors ###
$log test outputSet exists already in the Connect database
$onEmbeddedCode Connect:
- GAMSReader:
    symbols: [{'name': 'a'}, {'name': 'b'}, {'name': 'code_save'}]
- LabelManipulator:
    code:
        rule: x.split('-')[0]
        ruleIdentifier: x
        outputSet: code_save
$offEmbeddedCode
$if errorFree $abort 'Expect errors'
$clearErrors

$log test outputSet exists already in the Connect database (created by another LabelManipulator instance)
$onEmbeddedCode Connect:
- GAMSReader:
    symbols: [{'name': 'a'}, {'name': 'b'}]
- LabelManipulator:
    code:
        rule: x.split('-')[0]
        outputSet: save_set
- LabelManipulator:
    code:
        rule: f"{x}_new"
        outputSet: save_set
$offEmbeddedCode
$if errorFree $abort 'Expect errors'
$clearErrors

$log test map and case in the same LabelManipulator instance
$onEmbeddedCode Connect:
- GAMSReader:
    symbols: [{'name': 'a'}]
- LabelManipulator:
    map:
        setName: mapping_set
    case:
        rule: upper
$offEmbeddedCode
$if errorFree $abort 'Expect errors'
$clearErrors

$log test map and regex in the same LabelManipulator instance
$onEmbeddedCode Connect:
- GAMSReader:
    symbols: [{'name': 'a'}, {'name': 'inv_mapping_set'}]
- LabelManipulator:
    map:
        setName: inv_mapping_set
        invert: True
    regex:
        pattern: (\b\w{3})-(\w+\b)
        replace: \1\2
$offEmbeddedCode
$if errorFree $abort 'Expect errors'
$clearErrors

$log test map and code in the same LabelManipulator instance
$onEmbeddedCode Connect:
- GAMSReader:
    symbols: [{'name': 'a'}, {'name': 'mapping_set'}]
- LabelManipulator:
    map:
        setName: mapping_set
    code:
        rule: x.split('-')[0]
$offEmbeddedCode
$if errorFree $abort 'Expect errors)'
$clearErrors

$log test case and regex in the same LabelManipulator instance
$onEmbeddedCode Connect:
- GAMSReader:
    symbols: [{'name': 'a'}]
- LabelManipulator:
    case:
        rule: upper
    regex:
        pattern: (\b\w{3})-(\w+\b)
        replace: \1\2
$offEmbeddedCode
$if errorFree $abort 'Expect errors for multiple manipulators (4)'
$clearErrors

$log test case and code in the same LabelManipulator instance
$onEmbeddedCode Connect:
- GAMSReader:
    symbols: [{'name': 'a'}]
- LabelManipulator:
    case:
        rule: capitalize
    code:
        rule: y.split('-')[0]
        ruleIdentifier: y
$offEmbeddedCode
$if errorFree $abort 'Expect errors'
$clearErrors

$log test regex and code in the same LabelManipulator instance
$onEmbeddedCode Connect:
- GAMSReader:
    symbols: [{'name': 'a'}]
- LabelManipulator:
    regex:
        pattern: (\b\w{3})-(\w+\b)
        replace: \1\2
    code:
        rule: x.split('-')[0]
        ruleIdentifier: x
$offEmbeddedCode
$if errorFree $abort 'Expect errors'
$clearErrors

$log test code mode: invalid ruleIdentifier  
$onEmbeddedCode Connect:
- GAMSReader:
    symbols: [{'name': 'a'}, {'name': 'b'}]
- LabelManipulator:
    code:
        rule: t.split('-')[0]
        ruleIdentifier: x
$offEmbeddedCode
$if errorFree $abort 'Expect errors'
$clearErrors

$log test no mode provided
$onEmbeddedCode Connect:
- LabelManipulator:
    writeAll: True
$offEmbeddedCode
$if errorFree $abort 'Expect errors'
$clearErrors

$log test symbol does not exist
$onEmbeddedCode Connect:
- GAMSReader:
    symbols: [{'name': 'a'}]
- LabelManipulator:
    symbols: [{'name': 'e'}]
    case:
        rule: capitalize
$offEmbeddedCode
$if errorFree $abort 'Expect errors'
$clearErrors

$log test setName does not exist
$onEmbeddedCode Connect:
- GAMSReader:
    symbols: [{'name': 'a'}]
- LabelManipulator:
    map:
        setName: mapping_set
$offEmbeddedCode
$if errorFree $abort 'Expect errors'
$clearErrors

$log test setName is not a set
$onEmbeddedCode Connect:
- GAMSReader:
    symbols: [{'name': 'a'},{'name': 'b'} ]
- LabelManipulator:
    map:
        setName: b
$offEmbeddedCode
$if errorFree $abort 'Expect errors'
$clearErrors

$log ### test general unexpected errors ###
$log test that agent keeps all database symbols and case insensitivity of name
$onEmbeddedCode Connect:
- GAMSReader:
    readAll: True
- PythonCode:
    code: |
      if len(connect.container) != 16:
        raise Exception("Expected 16 symbols.")
- LabelManipulator:
    symbols:
      - name: A
    case:
        rule: upper
- PythonCode:
    code: |
      if len(connect.container) != 16:
        raise Exception("Expected 16 symbols.")
$offEmbeddedCode

$log test that agent adds a new symbol when newName is used and the original symbol remains unchanged
$onEmbeddedCode Connect:
- GAMSReader:
    readAll: True
- PythonCode:
    code: |
      if len(connect.container) != 16:
        raise Exception("Expected 16 symbols.")
- LabelManipulator:
    symbols:
      - name: a
        newName: a_new
    case:
        rule: upper
- PythonCode:
    code: |
      expected_a = [
        ['seattle', 350],
        ['san-diego', 600]     
      ]

      expected_a_new = [
        ['SEATTLE', 350],
        ['SAN-DIEGO', 600]     
      ]

      if len(connect.container) != 17:
        raise Exception("Expected 17 symbols.")
      if expected_a != connect.container['a'].records.values.tolist():
        raise Exception("Unexpected data (a)")
      if expected_a_new != connect.container['a_new'].records.values.tolist():
        raise Exception("Unexpected data (a_new)")
$offEmbeddedCode

$log test that agent changes labels of selected symbols only
$onEmbeddedCode Connect:
- GAMSReader:
    symbols: [{'name': 'c'}, {'name': 'i'}]
- LabelManipulator:
    symbols:
        - name: c
    case:
        rule: upper
        outputSet: save_set
- PythonCode:
    code: |
    
      expected_c = [
        ['SEATTLE', 'NEW-YORK', 0.225],
        ['SEATTLE', 'CHICAGO', 0.153],
        ['SEATTLE', 'TOPEKA', 0.162],
        ['SAN-DIEGO', 'NEW-YORK', 0.225],
        ['SAN-DIEGO', 'CHICAGO', 0.162],
        ['SAN-DIEGO', 'TOPEKA', 0.126]
        ]
        
      expected_i = [
        ['seattle', ''],
        ['san-diego', '']
        ]
        
      expected_s = [
        ['SEATTLE', 'seattle'],
        ['SAN-DIEGO', 'san-diego'],
        ['NEW-YORK', 'new-york'],
        ['CHICAGO', 'chicago'],
        ['TOPEKA', 'topeka']
        ]
    
      if expected_c != connect.container['c'].records.values.tolist():
        raise Exception("Unexpected data (c)")
      if expected_i != connect.container['i'].records.values.tolist():
        raise Exception("Unexpected data (i)")
      if expected_s != connect.container['save_set'].records.values.tolist():
        raise Exception("Unexpected data (save_set)")
$offEmbeddedCode

$log ### test case mode ###
$log test case mode: 'upper' case manipulation for a scalar
$onEmbeddedCode Connect:
- GAMSReader:
    symbols: [{'name': 'f'}]
- LabelManipulator:
    symbols: [{'name': 'f'}]
    case:
        rule: upper
- PythonCode:
    code: |
        expected = [
        [90.0]
        ]
        
        if expected != connect.container['f'].records.values.tolist():
            raise Exception("Unexpected data (f)")
$offEmbeddedCode

$log test case mode: 'upper' then 'lower' case manipulation for a 2-dim parameter
$onEmbeddedCode Connect:
- GAMSReader:
    symbols: [{'name': d}]
- LabelManipulator:
    case:
        rule: upper
- PythonCode:
    code: |
      expected_d_up = [
        ['SEATTLE', 'NEW-YORK', 2.5],
        ['SEATTLE', 'CHICAGO', 1.7],
        ['SEATTLE', 'TOPEKA', 1.8],
        ['SAN-DIEGO', 'NEW-YORK', 2.5],
        ['SAN-DIEGO', 'CHICAGO', 1.8],
        ['SAN-DIEGO', 'TOPEKA', 1.4]
      ]

      if expected_d_up != connect.container['d'].records.values.tolist():
        raise Exception("Unexpected data (d)")
- LabelManipulator:
    case:
        rule: lower
- PythonCode:
    code: |
      expected_d_lo = [
        ['seattle', 'new-york', 2.5],
        ['seattle', 'chicago', 1.7],
        ['seattle', 'topeka', 1.8],
        ['san-diego', 'new-york', 2.5],
        ['san-diego', 'chicago', 1.8],
        ['san-diego', 'topeka', 1.4]
      ]

      if expected_d_lo != connect.container['d'].records.values.tolist():
        raise Exception("Unexpected data (d)")
$offEmbeddedCode

$log test case mode: 'upper' case manipulation for 2-dim variable
$onEmbeddedCode Connect:
- GAMSReader:
    symbols: [{'name': 'x'}]
- LabelManipulator:
    case:
        rule: upper
- PythonCode:
    code: |
      expected = [
        ['SEATTLE', 'NEW-YORK', 50.0, 0.0, 0.0, float("inf"), 1.0],
        ['SEATTLE', 'CHICAGO', 300.0, 0.0, 0.0, float("inf"), 1.0],
        ['SEATTLE', 'TOPEKA', 0.0, 0.036, 0.0, float("inf"), 1.0],
        ['SAN-DIEGO', 'NEW-YORK', 275.0, 0.0, 0.0, float("inf"), 1.0],
        ['SAN-DIEGO', 'CHICAGO', 0.0, 0.009, 0.0, float("inf"), 1.0],
        ['SAN-DIEGO', 'TOPEKA', 275.0, 0.0, 0.0, float("inf"), 1.0]
      ]
      if expected != connect.container['x'].records.values.tolist():
        raise Exception("Unexpected data (x)")
$offEmbeddedCode


$log ### test code mode ###
$log test code mode: for two 1-dim parameters
$onEmbeddedCode Connect:
- GAMSReader:
    symbols: [{'name': 'a'}, {'name': 'b'}]
- LabelManipulator:
    code:
        rule: x.split('-')[0]
        ruleIdentifier: x
- PythonCode:
    code: |
      expected_a = [
        ['seattle', 350],
        ['san', 600]     
      ]
      expected_b = [
        ['new', 325],
        ['chicago', 300],
        ['topeka', 275]  
      ]
      if expected_a != connect.container['a'].records.values.tolist():
        raise Exception("Unexpected data (a)")
      if expected_b != connect.container['b'].records.values.tolist():
        raise Exception("Unexpected data (b)")
$offEmbeddedCode

$log test code mode: for two 1-dim parameters with outputSet
$onEmbeddedCode Connect:
- GAMSReader:
    symbols: [{'name': 'a'}, {'name': 'b'}]
- LabelManipulator:
    code:
        rule: ID.split('-')[0]
        ruleIdentifier: ID
        outputSet: save_set
- PythonCode:
    code: |
      expected_a = [
        ['seattle', 350],
        ['san', 600]     
      ]
      expected_b = [
        ['new', 325],
        ['chicago', 300],
        ['topeka', 275]  
      ]
      expected_s = [
        ['san', 'san-diego'],
        ['new', 'new-york']
      ]
      if expected_a != connect.container['a'].records.values.tolist():
        raise Exception("Unexpected data (a)")
      if expected_b != connect.container['b'].records.values.tolist():
        raise Exception("Unexpected data (b)")
      if expected_s != connect.container['save_set'].records.values.tolist():
        raise Exception("Unexpected data (s)")
$offEmbeddedCode

$log ### test regex mode ###
$log test regex mode: for 2-dim parameter
$onEmbeddedCode Connect:
- GAMSReader:
    symbols: [{'name': 'd'}]
- LabelManipulator:
    symbols: [{'name': 'd'}]
    regex:
        pattern: (\w+)-(\w+)
        replace: \1\2
- PythonCode:
    code: |
      expected = [
        ['seattle', 'newyork', 2.5],
        ['seattle', 'chicago', 1.7],
        ['seattle', 'topeka', 1.8],
        ['sandiego', 'newyork', 2.5],
        ['sandiego', 'chicago', 1.8],
        ['sandiego', 'topeka', 1.4]
      ]
      if expected != connect.container['d'].records.values.tolist():
        raise Exception("Unexpected data (d)")
$offEmbeddedCode

$log test regex mode: for two 1-dim sets
$onEmbeddedCode Connect:
- GAMSReader:
    symbols: [{'name': 'i'}, {'name': 'j'}]
- LabelManipulator:
    regex:
        pattern: '[^x]$'
        replace: '\g<0>x'
- PythonCode:
    code: |
      expected_i = [
        ['seattlex', ''], ['san-diegox', '']
      ]
      
      expected_j = [
        ['new-yorkx', ''],
        ['chicagox', ''],
        ['topekax', '']
      ]

      if expected_i != connect.container['i'].records.values.tolist():
        raise Exception("Unexpected data (i)")
      if expected_j != connect.container['j'].records.values.tolist():
        raise Exception("Unexpected data (j)")
$offEmbeddedCode


$log ### test map mode ###
$log test map mode: mapping set is not changed
$onEmbeddedCode Connect:
- GAMSReader:
    symbols: [{'name': 'c'}, {'name': 'mapping_set'}]
- LabelManipulator:
    writeAll: True
    map:
        setName: mapping_set
- PythonCode:
    code: |
      expected_c = [
        ['Braunschweig', 'new-york', 0.225],
        ['Braunschweig', 'Hannover', 0.153],
        ['Braunschweig', 'topeka', 0.162],
        ['san-diego', 'new-york', 0.225],
        ['san-diego', 'Hannover', 0.162],
        ['san-diego', 'topeka', 0.126]
      ]
      expected_s = [
        ['seattle', 'Braunschweig'],
        ['chicago', 'Hannover']
      ]

      if expected_c != connect.container['c'].records.values.tolist():
        raise Exception("Unexpected data (c)")
      if expected_s != connect.container['mapping_set'].records.values.tolist():
        raise Exception("Unexpected data (mapping_set)")
$offEmbeddedCode

$log test map mode: for two 1-dim sets
$onEmbeddedCode Connect:
- GAMSReader:
    symbols: [{'name': 'i'}, {'name': 'j'}, {'name': 'mapping_set'}]
- LabelManipulator:
    symbols: [{'name': 'i'}]
    map:
        setName: mapping_set
- LabelManipulator:
    symbols: [{'name': 'j'}]
    map:
        setName: mapping_set
- PythonCode:
    code: |
      expected_i = [
        ['Braunschweig', ''],
        ['san-diego', '']
      ]
      expected_j = [
        ['new-york', ''],
        ['Hannover', ''],
        ['topeka', '']
      ]
      if expected_i != connect.container['i'].records.values.tolist():
        raise Exception("Unexpected data (i)")
      if expected_j != connect.container['j'].records.values.tolist():
        raise Exception("Unexpected data (j)")
$offEmbeddedCode

$log test map mode: for two 1-dim sets with invert
$onEmbeddedCode Connect:
- GAMSReader:
    symbols: [{'name': 'i'}, {'name': 'j'}, {'name': 'inv_mapping_set'}]
- LabelManipulator:
    map:
        setName: inv_mapping_set
        invert: True
- PythonCode:
    code: |
      expected_i = [
        ['Braunschweig', ''],
        ['san-diego', '']
      ]
      expected_j = [
        ['new-york', ''],
        ['Hannover', ''],
        ['topeka', '']
      ]
      if expected_i != connect.container['i'].records.values.tolist():
        raise Exception("Unexpected data (i)")
      if expected_j != connect.container['j'].records.values.tolist():
        raise Exception("Unexpected data (j)")
$offEmbeddedCode

$log test map mode: for 1-dim parameter
$onEmbeddedCode Connect:
- GAMSReader:
    symbols: [{'name': 'b'}, {'name': 'j'}, {'name': 'mapping_set'}]
- LabelManipulator:
    symbols:
        - name: b
          newName: new_b
    map:
        setName: mapping_set
- PythonCode:
    code: |
      expected_j = [
        ['new-york', ''],
        ['chicago', ''],
        ['topeka', '']   
        ]
      expected_b = [
        ['new-york', 325],
        ['Hannover', 300],
        ['topeka', 275]
      ]
      if expected_b != connect.container['new_b'].records.values.tolist():
        raise Exception("Unexpected data (new_b)")
      if expected_j != connect.container['j'].records.values.tolist():
        raise Exception("Unexpected data (j)")
$offEmbeddedCode

$log test map mode: for a scalar
$onEmbeddedCode Connect:
- GAMSReader:
    symbols: [{'name': 'f'}, {'name': 'b'}, {'name': 'mapping_set'}]
- LabelManipulator:
    symbols:
        - name: f
          newName: new_f
    map:
        setName: mapping_set
- PythonCode:
    code: |
      expected_f = [[90.0]]
      expected_b = [
        ['new-york', 325],
        ['chicago', 300],
        ['topeka', 275]
      ]
      if expected_b != connect.container['b'].records.values.tolist():
        raise Exception("Unexpected data (b)")
      if expected_f != connect.container['new_f'].records.values.tolist():
        raise Exception("Unexpected data (new_f)")
$offEmbeddedCode

$log test map mode: for a 2-dim parameter with invert
$onEmbeddedCode Connect:
- GAMSReader:
    symbols: [{'name': 'd'}, {'name': 'inv_mapping_set'}]
- LabelManipulator:
    map:
        setName: inv_mapping_set
        invert: True
- PythonCode:
    code: |
      expected_d = [
        ['Braunschweig', 'new-york', 2.5],
        ['Braunschweig', 'Hannover', 1.7],
        ['Braunschweig', 'topeka', 1.8],
        ['san-diego', 'new-york', 2.5],
        ['san-diego', 'Hannover', 1.8],
        ['san-diego', 'topeka', 1.4]
        ]

      if expected_d != connect.container['d'].records.values.tolist():
        raise Exception("Unexpected data (d)")
$offEmbeddedCode

$log ### test case/map mode ###
$log test case/map mode: 'capitalize' case manipulation for two 1-dim sets with outputSet and map using the outputSet 
$onEmbeddedCode Connect:
- GAMSReader:
    symbols: [{'name': 'i'}, {'name': 'j'}]
- LabelManipulator:
    symbols:
        - name: i
          newName: i_cap
        - name: j
          newName: j_cap
    case:
        rule: capitalize
        outputSet: save_set
- PythonCode:
    code: |
      expected_i = [
        ['Seattle', ''],
        ['San-diego', '']
      ]
      expected_j = [
        ['New-york', ''],
        ['Chicago', ''],
        ['Topeka', '']
      ]
      expected_s = [
        ['Seattle', 'seattle'],
        ['San-diego', 'san-diego'],
        ['New-york', 'new-york'],
        ['Chicago', 'chicago'],
        ['Topeka', 'topeka']
      ]
      if expected_i != connect.container['i_cap'].records.values.tolist():
        raise Exception("Unexpected data (i_cap)")
      if expected_j != connect.container['j_cap'].records.values.tolist():
        raise Exception("Unexpected data (j_cap)")
      if expected_s != connect.container['save_set'].records.values.tolist():
        raise Exception("Unexpected data (save_set)")
- LabelManipulator:
    symbols:
        - name: i_cap
          newName: i_back
        - name: j_cap
          newName: j_back
    map:
        setName: save_set
- PythonCode:
    code: |
      if connect.container['i'].records.values.tolist() != connect.container['i_back'].records.values.tolist():
        raise Exception("Unexpected data (i_back)")
      if connect.container['j'].records.values.tolist() != connect.container['j_back'].records.values.tolist():
        raise Exception("Unexpected data (j_back)")
$offEmbeddedCode

$log ### test regex/map mode ###
$log test regex/map mode: regex manipulation for 2-dim parameter with outputSet and map using outputSet
$onEmbeddedCode Connect:
- GAMSReader:
    symbols: [{'name': 'd'}]
- LabelManipulator:
    symbols: [{'name': 'd', 'newName': 'd_reg'}]
    regex:
        pattern: (\b\w{3})-(\w+\b)
        replace: \1\2
        outputSet: save_set
- PythonCode:
    code: |
      expected_d = [
        ['seattle', 'newyork', 2.5],
        ['seattle', 'chicago', 1.7],
        ['seattle', 'topeka', 1.8],
        ['sandiego', 'newyork', 2.5],
        ['sandiego', 'chicago', 1.8],
        ['sandiego', 'topeka', 1.4]
      ]
      expected_s = [
        ['sandiego', 'san-diego'],
        ['newyork', 'new-york'],     
      ]

      if expected_d != connect.container['d_reg'].records.values.tolist():
        raise Exception("Unexpected data (d_reg)")
      if expected_s != connect.container['save_set'].records.values.tolist():
        raise Exception("Unexpected data (save_set)")
- LabelManipulator:
    symbols: [{'name': 'd_reg', 'newName': 'd_back'}]
    map:
        setName: save_set
- PythonCode:
    code: |
      if connect.container['d'].records.values.tolist() != connect.container['d_back'].records.values.tolist():
        raise Exception("Unexpected data (d_back)")
$offEmbeddedCode

$log ### test code/map mode ###
$log test code/map mode: for a 1-dim equation with outputSet and map using outputSet
$onEmbeddedCode Connect:
- GAMSReader:
    symbols: [{'name': 'demand'}]
- LabelManipulator:
    code:
        rule: f"eq_{x}"
        outputSet: save_set
- PythonCode:
    code: |
      expected_demand = [
        ['eq_new-york', 325.0, 0.225, 325.0, float("inf"), 1.0],
        ['eq_chicago', 300.0, 0.153, 300.0, float("inf"), 1.0],
        ['eq_topeka', 275.0, 0.126, 275.0, float("inf"), 1.0]
      ]

      if expected_demand != connect.container['demand'].records.values.tolist():
        raise Exception("Unexpected data (demand)")
- LabelManipulator:
    map:
        setName: save_set
- PythonCode:
    code: |
      expected_demand = [
        ['new-york', 325.0, 0.225, 325.0, float("inf"), 1.0],
        ['chicago', 300.0, 0.153, 300.0, float("inf"), 1.0],
        ['topeka', 275.0, 0.126, 275.0, float("inf"), 1.0]
        ]
      if expected_demand != connect.container['demand'].records.values.tolist():
        raise Exception("Unexpected data (demand)")
$offEmbeddedCode

$log test multiple identical target labels
$onecho > multi.csv
Label1, 2.5
LaBeL1, 1.7
label2, 1.8
$offEcho
$onEmbeddedCode Connect:
- CSVReader:
    header: False
    file: multi.csv
    name: p
    indexColumns: 1
    valueColumns: 2
- LabelManipulator:
    case:
      rule: lower
- PythonCode:
    code: |
      expected_p = [
        ['label1', 2.5],
        ['label1', 1.7],
        ['label2', 1.8],
      ]
      if expected_p != connect.container['p'].records.values.tolist():
        raise Exception("Unexpected data (p)")
$offEmbeddedCode