#!/usr/bin/env python

import os
import json
import sys
import unittest
import urllib2

from flexmock import flexmock

sys.path.append(os.path.join(os.path.dirname(__file__), "../../"))
import solr_interface
import search_exceptions

class FakeSolrDoc():
  def __init__(self):
    self.fields = []

class FakeDocument():
  INDEX_NAME = "indexname"
  INDEX_LOCALE = "indexlocale"
  def __init__(self):
    self.fields = []
    self.id = "id"
    self.language = "lang"

class FakeSchema():
  def __init__(self):
    self.fields = []

class FakeIndex():
  def __init__(self):
    self.name = "name"
    self.schema = FakeSchema()

class FakeIndexSpec():
  def __init__(self):
    pass
  def namespace(self):
    return 'ns'
  def name(self):
    return self.name

class FakeUpdate():
  def __init__(self, name, field_type):
    self.name = name
    self.field_type = field_type

class FakeConnection():
  def __init__(self, is_good_code):
    self.code = 200
    if not is_good_code:
      self.code = 500
  def getcode(self):
    return self.code

class TestSolrInterface(unittest.TestCase):
  """                                                                           
  A set of test cases for the solr interface module.
  """
  def test_get_index_adapter(self):
    appscale_info = flexmock()
    appscale_info.should_receive("get_search_location").\
      and_return("somelocation")
    solr = solr_interface.Solr()
    solr = flexmock(solr)
    flexmock(solr_interface)
    solr_interface.should_receive("get_index_name").and_return("index_ns_name")
    flexmock(urllib2)
    urllib2.should_receive("urlopen").and_return(FakeConnection(False))
    self.assertRaises(search_exceptions.InternalError,
                      solr._get_index_adapter, "app_id", "ns", "name")

    # Test the case of ValueError on a json.load.
    urllib2.should_receive("urlopen").and_return(FakeConnection(True))
    flexmock(json)
    json.should_receive("load").and_raise(ValueError)
    self.assertRaises(search_exceptions.InternalError,
                      solr._get_index_adapter, "app_id", "ns", "name")

    # Test a bad status from SOLR.
    dictionary = {'responseHeader':{'status': 1}}
    json.should_receive("load").and_return(dictionary)
    self.assertRaises(search_exceptions.InternalError,
                      solr._get_index_adapter, "app_id", "ns", "name")

    fields = [{'name':"index_ns_name_"}]
    dictionary = {'responseHeader':{'status': 0}, "fields": fields}
    json.should_receive("load").and_return(dictionary)
    index = solr._get_index_adapter("app_id", "ns", "name")
    self.assertEquals(index.schema[0]['name'], "index_ns_name_")

  def test_update_schema(self):
    appscale_info = flexmock()
    appscale_info.should_receive("get_search_location").\
      and_return("somelocation")
    solr = solr_interface.Solr()

    flexmock(urllib2)
    urllib2.should_receive("urlopen").and_return(FakeConnection(False))
    updates = []
    self.assertRaises(search_exceptions.InternalError,
                      solr.update_schema, updates)

    updates = [{'name': 'name1', 'type':'type1'}]
    flexmock(json)
    json.should_receive("load").and_raise(ValueError)
    urllib2.should_receive("urlopen").and_return(FakeConnection(True))
    self.assertRaises(search_exceptions.InternalError,
                      solr.update_schema, updates)

    dictionary = {"responseHeader":{"status":1}}
    json.should_receive("load").and_return(dictionary)
    self.assertRaises(search_exceptions.InternalError,
                      solr.update_schema, updates)

    dictionary = {"responseHeader":{"status":0}}
    json.should_receive("load").and_return(dictionary)
    solr.update_schema(updates)

  def test_to_solr_hash_map(self):
    appscale_info = flexmock()
    appscale_info.should_receive("get_search_location").\
      and_return("somelocation")
    solr = solr_interface.Solr()
    self.assertNotEqual(solr.to_solr_hash_map(FakeIndex(), FakeDocument()), {})

  def test_commit_update(self):
    appscale_info = flexmock()
    appscale_info.should_receive("get_search_location").\
      and_return("somelocation")
    solr = solr_interface.Solr()

    flexmock(json)
    json.should_receive("loads").and_return({})

    flexmock(urllib2)
    urllib2.should_receive("urlopen").and_return(FakeConnection(False))
    self.assertRaises(search_exceptions.InternalError, solr.commit_update, {})

    json.should_receive("load").and_raise(ValueError)
    urllib2.should_receive("urlopen").and_return(FakeConnection(True))
    self.assertRaises(search_exceptions.InternalError, solr.commit_update, {})

    dictionary = {'responseHeader':{'status': 1}}
    json.should_receive("load").and_return(dictionary).once()
    self.assertRaises(search_exceptions.InternalError, solr.commit_update, {})

    dictionary = {'responseHeader':{'status': 0}}
    json.should_receive("load").and_return(dictionary).once()
    solr.commit_update({})

  def test_update_document(self):
    appscale_info = flexmock()
    appscale_info.should_receive("get_search_location").\
      and_return("somelocation")
    solr = solr_interface.Solr()
    solr = flexmock(solr)
    solr.should_receive("to_solr_doc").and_return(FakeSolrDoc())
    solr.should_receive("_get_index_adapter").and_return(FakeIndex())
    solr.should_receive("compute_updates").and_return([])
    solr.should_receive("to_solr_hash_map").and_return(None)
    solr.should_receive("commit_update").and_return(None)
    solr.update_document("app_id", None, FakeIndexSpec())

    solr.should_receive("compute_updates").and_return([1,2])
    solr.should_receive("update_schema").twice()
    solr.update_document("app_id", None, FakeIndexSpec())

    solr.should_receive("to_solr_hash_map").and_return(None).once()
    solr.update_document("app_id", None, FakeIndexSpec())

  def test_json_loads_byteified(self):
    json_with_unicode = (
      '{"key2": [{"\\u2611": 28, "\\u2616": ["\\u263a"]}, "second", "third"], '
      '"key1": "value", '
      '"\\u2604": {"\\u2708": "\\u2708"}}'
    )
    parsed_obj = solr_interface.json_loads_byteified(json_with_unicode)

    def walk_and_check_type(obj):
      if isinstance(obj, dict):
        for key, value in obj.iteritems():
          self.assertIsInstance(key, str)
          walk_and_check_type(value)
      elif isinstance(obj, list):
        for value in obj:
          walk_and_check_type(value)
      else:
        self.assertIsInstance(obj, (str, int))

    walk_and_check_type(parsed_obj)
    self.assertEqual(parsed_obj, {
      'key1': 'value',
      'key2': [
        {'\xe2\x98\x91': 28, '\xe2\x98\x96': ['\xe2\x98\xba']},
        'second',
        'third'
      ],
      '\xe2\x98\x84': {'\xe2\x9c\x88': '\xe2\x9c\x88'}
    })

[((11, 29, 11, 54), 'os.path.dirname', 'os.path.dirname', ({(11, 45, 11, 53): '__file__'}, {}), '(__file__)', False, 'import os\n'), ((62, 20, 62, 30), 'flexmock.flexmock', 'flexmock', ({}, {}), '()', False, 'from flexmock import flexmock\n'), ((65, 11, 65, 32), 'solr_interface.Solr', 'solr_interface.Solr', ({}, {}), '()', False, 'import solr_interface\n'), ((66, 11, 66, 25), 'flexmock.flexmock', 'flexmock', ({(66, 20, 66, 24): 'solr'}, {}), '(solr)', False, 'from flexmock import flexmock\n'), ((67, 4, 67, 28), 'flexmock.flexmock', 'flexmock', ({(67, 13, 67, 27): 'solr_interface'}, {}), '(solr_interface)', False, 'from flexmock import flexmock\n'), ((69, 4, 69, 21), 'flexmock.flexmock', 'flexmock', ({(69, 13, 69, 20): 'urllib2'}, {}), '(urllib2)', False, 'from flexmock import flexmock\n'), ((76, 4, 76, 18), 'flexmock.flexmock', 'flexmock', ({(76, 13, 76, 17): 'json'}, {}), '(json)', False, 'from flexmock import flexmock\n'), ((94, 20, 94, 30), 'flexmock.flexmock', 'flexmock', ({}, {}), '()', False, 'from flexmock import flexmock\n'), ((97, 11, 97, 32), 'solr_interface.Solr', 'solr_interface.Solr', ({}, {}), '()', False, 'import solr_interface\n'), ((99, 4, 99, 21), 'flexmock.flexmock', 'flexmock', ({(99, 13, 99, 20): 'urllib2'}, {}), '(urllib2)', False, 'from flexmock import flexmock\n'), ((106, 4, 106, 18), 'flexmock.flexmock', 'flexmock', ({(106, 13, 106, 17): 'json'}, {}), '(json)', False, 'from flexmock import flexmock\n'), ((122, 20, 122, 30), 'flexmock.flexmock', 'flexmock', ({}, {}), '()', False, 'from flexmock import flexmock\n'), ((125, 11, 125, 32), 'solr_interface.Solr', 'solr_interface.Solr', ({}, {}), '()', False, 'import solr_interface\n'), ((129, 20, 129, 30), 'flexmock.flexmock', 'flexmock', ({}, {}), '()', False, 'from flexmock import flexmock\n'), ((132, 11, 132, 32), 'solr_interface.Solr', 'solr_interface.Solr', ({}, {}), '()', False, 'import solr_interface\n'), ((134, 4, 134, 18), 'flexmock.flexmock', 'flexmock', ({(134, 13, 134, 17): 'json'}, {}), '(json)', False, 'from flexmock import flexmock\n'), ((137, 4, 137, 21), 'flexmock.flexmock', 'flexmock', ({(137, 13, 137, 20): 'urllib2'}, {}), '(urllib2)', False, 'from flexmock import flexmock\n'), ((154, 20, 154, 30), 'flexmock.flexmock', 'flexmock', ({}, {}), '()', False, 'from flexmock import flexmock\n'), ((157, 11, 157, 32), 'solr_interface.Solr', 'solr_interface.Solr', ({}, {}), '()', False, 'import solr_interface\n'), ((158, 11, 158, 25), 'flexmock.flexmock', 'flexmock', ({(158, 20, 158, 24): 'solr'}, {}), '(solr)', False, 'from flexmock import flexmock\n'), ((179, 17, 179, 71), 'solr_interface.json_loads_byteified', 'solr_interface.json_loads_byteified', ({(179, 53, 179, 70): 'json_with_unicode'}, {}), '(json_with_unicode)', False, 'import solr_interface\n'), ((68, 4, 68, 51), 'solr_interface.should_receive', 'solr_interface.should_receive', ({(68, 34, 68, 50): '"""get_index_name"""'}, {}), "('get_index_name')", False, 'import solr_interface\n'), ((70, 4, 70, 37), 'urllib2.should_receive', 'urllib2.should_receive', ({(70, 27, 70, 36): '"""urlopen"""'}, {}), "('urlopen')", False, 'import urllib2\n'), ((75, 4, 75, 37), 'urllib2.should_receive', 'urllib2.should_receive', ({(75, 27, 75, 36): '"""urlopen"""'}, {}), "('urlopen')", False, 'import urllib2\n'), ((77, 4, 77, 31), 'json.should_receive', 'json.should_receive', ({(77, 24, 77, 30): '"""load"""'}, {}), "('load')", False, 'import json\n'), ((83, 4, 83, 31), 'json.should_receive', 'json.should_receive', ({(83, 24, 83, 30): '"""load"""'}, {}), "('load')", False, 'import json\n'), ((89, 4, 89, 31), 'json.should_receive', 'json.should_receive', ({(89, 24, 89, 30): '"""load"""'}, {}), "('load')", False, 'import json\n'), ((100, 4, 100, 37), 'urllib2.should_receive', 'urllib2.should_receive', ({(100, 27, 100, 36): '"""urlopen"""'}, {}), "('urlopen')", False, 'import urllib2\n'), ((107, 4, 107, 31), 'json.should_receive', 'json.should_receive', ({(107, 24, 107, 30): '"""load"""'}, {}), "('load')", False, 'import json\n'), ((108, 4, 108, 37), 'urllib2.should_receive', 'urllib2.should_receive', ({(108, 27, 108, 36): '"""urlopen"""'}, {}), "('urlopen')", False, 'import urllib2\n'), ((113, 4, 113, 31), 'json.should_receive', 'json.should_receive', ({(113, 24, 113, 30): '"""load"""'}, {}), "('load')", False, 'import json\n'), ((118, 4, 118, 31), 'json.should_receive', 'json.should_receive', ({(118, 24, 118, 30): '"""load"""'}, {}), "('load')", False, 'import json\n'), ((135, 4, 135, 32), 'json.should_receive', 'json.should_receive', ({(135, 24, 135, 31): '"""loads"""'}, {}), "('loads')", False, 'import json\n'), ((138, 4, 138, 37), 'urllib2.should_receive', 'urllib2.should_receive', ({(138, 27, 138, 36): '"""urlopen"""'}, {}), "('urlopen')", False, 'import urllib2\n'), ((141, 4, 141, 31), 'json.should_receive', 'json.should_receive', ({(141, 24, 141, 30): '"""load"""'}, {}), "('load')", False, 'import json\n'), ((142, 4, 142, 37), 'urllib2.should_receive', 'urllib2.should_receive', ({(142, 27, 142, 36): '"""urlopen"""'}, {}), "('urlopen')", False, 'import urllib2\n'), ((146, 4, 146, 31), 'json.should_receive', 'json.should_receive', ({(146, 24, 146, 30): '"""load"""'}, {}), "('load')", False, 'import json\n'), ((150, 4, 150, 31), 'json.should_receive', 'json.should_receive', ({(150, 24, 150, 30): '"""load"""'}, {}), "('load')", False, 'import json\n')]