text: # This script creates Rust test cases from the common uritemplate-test data
  # files. The path of the JSON file should be passed in as a command line
  # argument.
  #
  # Example usage:
  #     python generate_tests.py uritemplate-test/extended-tests.json > ../tests/extended_tests.rs
  
  import json
  import sys
  import hashlib
  
  def compute_md5(s):
      m = hashlib.md5()
      m.update(s.encode('utf-8'))
      return m.hexdigest()
  
  TEST_NAMES = {
      'Level 1 Examples': 'test_level_1',
      'Level 2 Examples': 'test_level_2',
      'Level 3 Examples': 'test_level_3',
      'Level 4 Examples': 'test_level_4',
      '3.2.1 Variable Expansion': 'test_321_variable_expansion',
      '3.2.2 Simple String Expansion': 'test_322_simple_string_expansion',
      '3.2.3 Reserved Expansion': 'test_323_reserved_expansion',
      '3.2.4 Fragment Expansion': 'test_324_fragment_expansion',
      '3.2.5 Label Expansion with Dot-Prefix': 'test_325_label_expansion_with_dot_prefix',
      '3.2.6 Path Segment Expansion': 'test_326_path_segment_expansion',
      '3.2.7 Path-Style Parameter Expansion': 'test_327_path_style_parameter_expansion',
      '3.2.8 Form-Style Query Expansion': 'test_328_form_style_query_expansion',
      '3.2.9 Form-Style Query Continuation': 'test_329_form_style_query_continuation',
      'Additional Examples 1': 'test_additional_examples_1',
      'Additional Examples 2': 'test_additional_examples_2',
      'Additional Examples 3: Empty Variables': 'test_additional_examples_3',
      'Additional Examples 4: Numeric Keys': 'test_additional_examples_4'
  }
  
  # Load JSON file from command line argument
  file_path = sys.argv[1]
  with open(file_path) as json_file:
      data = json.load(json_file)
  
  # Print headers
  print('// File autogenerated with /scripts/generate_tests.py\n')
  print('extern crate uritemplate;')
  print('use uritemplate::UriTemplate;\n')
  
  # Create tests from JSON file
  for (idx, title) in enumerate(sorted(data)):
      # Write function header
      test_name = TEST_NAMES.get(title, 'test_' + compute_md5(title))
      print('// %s' % title)
      print('#[test]')
      print('fn %s() {' % test_name)
  
      # Create list of URI Templates
      print('    let mut templates = [')
      for template in (x[0] for x in data[title]['testcases']):
          print('        UriTemplate::new("%s"),' % template)
      print('    ];\n')
  
      # Set variables for all templates
      print('    for i in 0..templates.len() {')
      for var in data[title]['variables']:
          val = data[title]['variables'][var]
          if isinstance(val, str) or isinstance(val, int) or isinstance(val, float):
              val = '"%s"' % val
          elif isinstance(val, list):
              val = '&[%s] as &[&str]' % ", ".join('"%s"' % x for x in val)
          elif isinstance(val, dict):
              val = '&[%s] as &[(&str, &str)]' % ", ".join('("%s", "%s")' % (k, v) for (k, v) in val.items())
          elif val == None:
              continue
          else:
              raise Exception('Variable value is not a string, list, dictionary, or false')
          print('        templates[i].set("%s", %s);' % (var, val))
      print('    }\n')
  
      # Write assertions
      num_tests = len(data[title]['testcases'])
      for i in range(num_tests):
          answer = data[title]['testcases'][i][1]
          if isinstance(answer, str):
              print('    assert_eq!(templates[%d].build(), "%s");' % (i, answer))
          elif isinstance(answer, list):
              print('    let template_%d_answers = vec![' % i)
              for s in answer:
                  print('        "%s",' % s)
              print('    ];')
              print('    assert!(template_%d_answers.contains(&templates[%d].build().as_ref()));' % (i, i))
          else:
              raise Exception('Test answer is neither a string nor a list')
  
      # Close out function
      print('}')
      if idx != len(data) - 1:
          print()
  