#!/usr/bin/python
#
# Copyright (C) 2010, Nokia <ivan.frade@nokia.com>
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
# 02110-1301, USA.
#

"""
Peculiar Sparql behavour reported in bugs
"""
import sys,os,dbus
import unittest
import time
import random
import string
import datetime

from common.utils import configuration as cfg
import unittest2 as ut
#import unittest as ut
from common.utils.storetest import CommonTrackerStoreTest as CommonTrackerStoreTest
from common.utils.expectedFailure import expectedFailureBug


class TrackerStoreSparqlBugsTests (CommonTrackerStoreTest):

        def test_01_NB217566_union_exists_filter (self):
                """
                NB217566: Use of UNION in EXISTS in a FILTER breaks filtering 
                """
                content = """
                INSERT {
                    <contact:affiliation> a nco:Affiliation ;
                             nco:hasPhoneNumber
                                  [ a nco:PhoneNumber ; maemo:localPhoneNumber "98653" ] .
                    <contact:test> a nco:PersonContact ;
                             nco:hasAffiliation <contact:affiliation> .
                }
                """
                self.tracker.update (content)

                """ Check that these 3 queries return the same results """
                query1 = """
                SELECT  ?_contact ?n WHERE {
                   ?_contact a nco:PersonContact .
                   {
                     ?_contact nco:hasAffiliation ?a .
                     ?a nco:hasPhoneNumber ?p1 .
                     ?p1 maemo:localPhoneNumber ?n
                   } UNION {
                     ?_contact nco:hasPhoneNumber ?p2 .
                     ?p2 maemo:localPhoneNumber ?n
                   } .
                  FILTER (
                    EXISTS {
                        {
                          ?_contact nco:hasPhoneNumber ?auto81 .
                          ?auto81 maemo:localPhoneNumber ?auto80
                        } UNION {
                          ?_contact nco:hasAffiliation ?auto83 .
                          ?auto83 nco:hasPhoneNumber ?auto84 .
                          ?auto84 maemo:localPhoneNumber ?auto80
                        }
                        FILTER (?auto80 = '98653')
                     }
                  )
                }
                """

                query2 = """
                SELECT ?_contact ?n WHERE {
                    ?_contact a nco:PersonContact .
                    {
                        ?_contact nco:hasAffiliation ?a .
                        ?a nco:hasPhoneNumber ?p1 .
                        ?p1 maemo:localPhoneNumber ?n
                    } UNION {
                        ?_contact nco:hasPhoneNumber ?p2 .
                        ?p2 maemo:localPhoneNumber ?n
                    } .
                    FILTER(?n = '98653')
                }
                """

                query3 = """
                SELECT ?_contact ?n WHERE {
                    ?_contact a nco:PersonContact .
                    {
                        ?_contact nco:hasAffiliation ?a .
                        ?a nco:hasPhoneNumber ?p1 .
                        ?p1 maemo:localPhoneNumber ?n
                    } UNION {
                        ?_contact nco:hasPhoneNumber ?p2 .
                        ?p2 maemo:localPhoneNumber ?n
                    } .
                    FILTER(
                        EXISTS {
                            ?_contact nco:hasAffiliation ?auto83 .
                            ?auto83 nco:hasPhoneNumber ?auto84 .
                            ?auto84 maemo:localPhoneNumber ?auto80 
                            FILTER(?auto80 = "98653")
                        }
                    )
                }
                """

                results1 = self.tracker.query (query1)
                print "1", results1
                self.assertEquals (len (results1), 1)
                self.assertEquals (len (results1[0]), 2)
                self.assertEquals (results1[0][0], "contact:test")
                self.assertEquals (results1[0][1], "98653")

                results2 = self.tracker.query (query2)
                print "2", results2
                self.assertEquals (len (results2), 1)
                self.assertEquals (len (results2[0]), 2)
                self.assertEquals (results2[0][0], "contact:test")
                self.assertEquals (results2[0][1], "98653")
                

                results3 = self.tracker.query (query3)
                print "3", results3
                self.assertEquals (len (results3), 1)
                self.assertEquals (len (results3[0]), 2)
                self.assertEquals (results3[0][0], "contact:test")
                self.assertEquals (results3[0][1], "98653")

                """ Clean the DB """
                delete = """
                DELETE { <contact:affiliation> a rdfs:Resource .
                <contact:test> a rdfs:Resource .
                }
                """ 
                
        def test_02_NB217636_delete_statements (self):
                """
                Bug 217636 - Not able to delete contact using
                DELETE {<contact:556> ?p ?v} WHERE {<contact:556> ?p ?v}.
                """
                data = """ INSERT {
                   <contact:test-nb217636> a nco:PersonContact ;
                          nco:fullname 'Testing bug 217636'
                }
                """
                self.tracker.update (data)

                results = self.tracker.query ("""
                 SELECT ?u WHERE {
                    ?u a nco:PersonContact ;
                      nco:fullname 'Testing bug 217636' .
                      }
                      """)
                self.assertEquals (len (results), 1)
                self.assertEquals (len (results[0]), 1)
                self.assertEquals (results[0][0], "contact:test-nb217636")

                problematic_delete = """
                DELETE { <contact:test-nb217636> ?p ?v }
                WHERE  { <contact:test-nb217636> ?p ?v }
                """
                self.tracker.update (problematic_delete)

                results_after = self.tracker.query ("""
                 SELECT ?u WHERE {
                    ?u a nco:PersonContact ;
                      nco:fullname 'Testing bug 217636' .
                      }
                      """)
                self.assertEquals (len (results_after), 0)

                # Safe deletion
                delete = """
                DELETE { <contact:test-nb217636> a rdfs:Resource. }
                """
                self.tracker.update (delete)


        def test_03_NB222645_non_existing_class_resource (self):
                """
                NB222645 - Inserting a resource using an non-existing class, doesn't rollback completely
                """
                query = "SELECT tracker:modified (?u) ?u  WHERE { ?u a nco:Contact }"
                original_data = self.tracker.query (query)

                wrong_insert = "INSERT { <test://nb222645-wrong-class-contact> a nco:IMContact. } "
                self.assertRaises (dbus.DBusException,
                                   self.tracker.update,
                                   wrong_insert)

                new_data = self.tracker.query (query)
                self.assertEquals (len (original_data), len (new_data))
                # We could be more picky, but checking there are the same number of results
                # is enough to verify the problem described in the bug.


        def test_04_NB224760_too_long_filter (self):
                """
                NB#224760 - 'too many sql variables' when filter ?sth in (long list)
                """
                query = "SELECT tracker:id (?m) ?m WHERE { ?m a rdfs:Resource. FILTER (tracker:id (?m) in (%s)) }"
                numbers = ",".join ([str (i) for i in range (1000, 2000)])

                results = self.tracker.query (query % (numbers))

                # The query will raise an exception is the bug is there
                # If we are here, everything is fine. 
                self.assertIsNotNone (results)
                                   
        def test_05_NB281201_insert_replace_and_superproperties (self):
                """
                Bug 281201 - INSERT OR REPLACE does not delete previous values for superproperties
                """
                content = """INSERT { <test:resource:nb281201> a nie:InformationElement; 
                                               nie:contentLastModified '2011-09-27T11:11:11Z'. }"""
                self.tracker.update (content)

                query = """SELECT ?contentLM ?nieIEDate ?dcDate { 
                              <test:resource:nb281201> dc:date ?dcDate ;
                                                 nie:informationElementDate ?nieIEDate ;
                                                 nie:contentLastModified ?contentLM .
                           }"""
                result = self.tracker.query (query)
                # Only one row of results, and the 3 colums have the same value
                self.assertEquals (len (result), 1)
                self.assertEquals (result[0][0], result[0][1])
                self.assertEquals (result[0][1], result[0][2])

                problematic = """INSERT OR REPLACE {
                                   <test:resource:nb281201> nie:contentLastModified '2012-10-28T12:12:12'
                                 }"""
                
                self.tracker.update (problematic)

                result = self.tracker.query (query)
                # Only one row of results, and the 3 colums have the same value
                self.assertEquals (len (result), 1)
                self.assertEquals (result[0][0], result[0][1])
                self.assertEquals (result[0][1], result[0][2])
                



if __name__ == "__main__":
	ut.main()
