#!/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'}
    })

[((148, 173), 'os.path.dirname', 'os.path.dirname', (['__file__'], {}), '(__file__)\n', (163, 173), False, 'import os\n'), ((1287, 1297), 'flexmock.flexmock', 'flexmock', ([], {}), '()\n', (1295, 1297), False, 'from flexmock import flexmock\n'), ((1400, 1421), 'solr_interface.Solr', 'solr_interface.Solr', ([], {}), '()\n', (1419, 1421), False, 'import solr_interface\n'), ((1433, 1447), 'flexmock.flexmock', 'flexmock', (['solr'], {}), '(solr)\n', (1441, 1447), False, 'from flexmock import flexmock\n'), ((1452, 1476), 'flexmock.flexmock', 'flexmock', (['solr_interface'], {}), '(solr_interface)\n', (1460, 1476), False, 'from flexmock import flexmock\n'), ((1561, 1578), 'flexmock.flexmock', 'flexmock', (['urllib2'], {}), '(urllib2)\n', (1569, 1578), False, 'from flexmock import flexmock\n'), ((1903, 1917), 'flexmock.flexmock', 'flexmock', (['json'], {}), '(json)\n', (1911, 1917), False, 'from flexmock import flexmock\n'), ((2708, 2718), 'flexmock.flexmock', 'flexmock', ([], {}), '()\n', (2716, 2718), False, 'from flexmock import flexmock\n'), ((2821, 2842), 'solr_interface.Solr', 'solr_interface.Solr', ([], {}), '()\n', (2840, 2842), False, 'import solr_interface\n'), ((2848, 2865), 'flexmock.flexmock', 'flexmock', (['urllib2'], {}), '(urllib2)\n', (2856, 2865), False, 'from flexmock import flexmock\n'), ((3116, 3130), 'flexmock.flexmock', 'flexmock', (['json'], {}), '(json)\n', (3124, 3130), False, 'from flexmock import flexmock\n'), ((3766, 3776), 'flexmock.flexmock', 'flexmock', ([], {}), '()\n', (3774, 3776), False, 'from flexmock import flexmock\n'), ((3879, 3900), 'solr_interface.Solr', 'solr_interface.Solr', ([], {}), '()\n', (3898, 3900), False, 'import solr_interface\n'), ((4034, 4044), 'flexmock.flexmock', 'flexmock', ([], {}), '()\n', (4042, 4044), False, 'from flexmock import flexmock\n'), ((4147, 4168), 'solr_interface.Solr', 'solr_interface.Solr', ([], {}), '()\n', (4166, 4168), False, 'import solr_interface\n'), ((4174, 4188), 'flexmock.flexmock', 'flexmock', (['json'], {}), '(json)\n', (4182, 4188), False, 'from flexmock import flexmock\n'), ((4242, 4259), 'flexmock.flexmock', 'flexmock', (['urllib2'], {}), '(urllib2)\n', (4250, 4259), False, 'from flexmock import flexmock\n'), ((5003, 5013), 'flexmock.flexmock', 'flexmock', ([], {}), '()\n', (5011, 5013), False, 'from flexmock import flexmock\n'), ((5116, 5137), 'solr_interface.Solr', 'solr_interface.Solr', ([], {}), '()\n', (5135, 5137), False, 'import solr_interface\n'), ((5149, 5163), 'flexmock.flexmock', 'flexmock', (['solr'], {}), '(solr)\n', (5157, 5163), False, 'from flexmock import flexmock\n'), ((6068, 6122), 'solr_interface.json_loads_byteified', 'solr_interface.json_loads_byteified', (['json_with_unicode'], {}), '(json_with_unicode)\n', (6103, 6122), False, 'import solr_interface\n'), ((1481, 1528), 'solr_interface.should_receive', 'solr_interface.should_receive', (['"""get_index_name"""'], {}), "('get_index_name')\n", (1510, 1528), False, 'import solr_interface\n'), ((1583, 1616), 'urllib2.should_receive', 'urllib2.should_receive', (['"""urlopen"""'], {}), "('urlopen')\n", (1605, 1616), False, 'import urllib2\n'), ((1832, 1865), 'urllib2.should_receive', 'urllib2.should_receive', (['"""urlopen"""'], {}), "('urlopen')\n", (1854, 1865), False, 'import urllib2\n'), ((1922, 1949), 'json.should_receive', 'json.should_receive', (['"""load"""'], {}), "('load')\n", (1941, 1949), False, 'import json\n'), ((2188, 2215), 'json.should_receive', 'json.should_receive', (['"""load"""'], {}), "('load')\n", (2207, 2215), False, 'import json\n'), ((2479, 2506), 'json.should_receive', 'json.should_receive', (['"""load"""'], {}), "('load')\n", (2498, 2506), False, 'import json\n'), ((2870, 2903), 'urllib2.should_receive', 'urllib2.should_receive', (['"""urlopen"""'], {}), "('urlopen')\n", (2892, 2903), False, 'import urllib2\n'), ((3135, 3162), 'json.should_receive', 'json.should_receive', (['"""load"""'], {}), "('load')\n", (3154, 3162), False, 'import json\n'), ((3189, 3222), 'urllib2.should_receive', 'urllib2.should_receive', (['"""urlopen"""'], {}), "('urlopen')\n", (3211, 3222), False, 'import urllib2\n'), ((3416, 3443), 'json.should_receive', 'json.should_receive', (['"""load"""'], {}), "('load')\n", (3435, 3443), False, 'import json\n'), ((3627, 3654), 'json.should_receive', 'json.should_receive', (['"""load"""'], {}), "('load')\n", (3646, 3654), False, 'import json\n'), ((4193, 4221), 'json.should_receive', 'json.should_receive', (['"""loads"""'], {}), "('loads')\n", (4212, 4221), False, 'import json\n'), ((4264, 4297), 'urllib2.should_receive', 'urllib2.should_receive', (['"""urlopen"""'], {}), "('urlopen')\n", (4286, 4297), False, 'import urllib2\n'), ((4416, 4443), 'json.should_receive', 'json.should_receive', (['"""load"""'], {}), "('load')\n", (4435, 4443), False, 'import json\n'), ((4470, 4503), 'urllib2.should_receive', 'urllib2.should_receive', (['"""urlopen"""'], {}), "('urlopen')\n", (4492, 4503), False, 'import urllib2\n'), ((4671, 4698), 'json.should_receive', 'json.should_receive', (['"""load"""'], {}), "('load')\n", (4690, 4698), False, 'import json\n'), ((4863, 4890), 'json.should_receive', 'json.should_receive', (['"""load"""'], {}), "('load')\n", (4882, 4890), False, 'import json\n')]