Mercurial > p > roundup > code
comparison test/db_test_base.py @ 6332:6a6b4651be1f
Use server-side cursor for postgres in some cases
In filter, filter_iter, and _materialize_multilinks, use named cursor
with postgresql. This turns of client-side cursor handling and avoids
*large* roundup process (or wsgi process) in case of large results.
Fixes issue2551114.
| author | Ralf Schlatterbeck <rsc@runtux.com> |
|---|---|
| date | Thu, 04 Mar 2021 12:55:21 +0100 |
| parents | 778a9f455067 |
| children | 0db59cc2cd37 |
comparison
equal
deleted
inserted
replaced
| 6331:c547e05d7a54 | 6332:6a6b4651be1f |
|---|---|
| 175 self.open_database() | 175 self.open_database() |
| 176 setupSchema(self.db, 1, self.module) | 176 setupSchema(self.db, 1, self.module) |
| 177 | 177 |
| 178 def iterSetup(self, classname='issue'): | 178 def iterSetup(self, classname='issue'): |
| 179 cls = getattr(self.db, classname) | 179 cls = getattr(self.db, classname) |
| 180 def filt_iter(*args, **kw): | 180 def filt_iter_list(*args, **kw): |
| 181 """ for checking equivalence of filter and filter_iter """ | 181 """ for checking equivalence of filter and filter_iter """ |
| 182 return list(cls.filter_iter(*args, **kw)) | 182 return list(cls.filter_iter(*args, **kw)) |
| 183 return self.assertEqual, cls.filter, filt_iter | 183 def filter_test_iterator(): |
| 184 """ yield all filter variants with config settings changed | |
| 185 appropriately | |
| 186 """ | |
| 187 self.db.config.RDBMS_SERVERSIDE_CURSOR = False | |
| 188 yield (cls.filter) | |
| 189 yield (filt_iter_list) | |
| 190 self.db.config.RDBMS_SERVERSIDE_CURSOR = True | |
| 191 yield (cls.filter) | |
| 192 yield (filt_iter_list) | |
| 193 return self.assertEqual, filter_test_iterator | |
| 184 | 194 |
| 185 def filteringSetupTransitiveSearch(self, classname='issue'): | 195 def filteringSetupTransitiveSearch(self, classname='issue'): |
| 186 u_m = {} | 196 u_m = {} |
| 187 k = 30 | 197 k = 30 |
| 188 for user in ( | 198 for user in ( |
| 491 if commit: self.db.commit() | 501 if commit: self.db.commit() |
| 492 self.assertEqual(self.db.issue.get(nid, "deadline"), None) | 502 self.assertEqual(self.db.issue.get(nid, "deadline"), None) |
| 493 | 503 |
| 494 def testDateSort(self): | 504 def testDateSort(self): |
| 495 d1 = date.Date('.') | 505 d1 = date.Date('.') |
| 496 ae, filter, filter_iter = self.filteringSetup() | 506 ae, iiter = self.filteringSetup() |
| 497 nid = self.db.issue.create(title="nodeadline", status='1') | 507 nid = self.db.issue.create(title="nodeadline", status='1') |
| 498 self.db.commit() | 508 self.db.commit() |
| 499 for filt in filter, filter_iter: | 509 for filt in iiter(): |
| 500 ae(filt(None, {}, ('+','deadline')), ['5', '2', '1', '3', '4']) | 510 ae(filt(None, {}, ('+','deadline')), ['5', '2', '1', '3', '4']) |
| 501 ae(filt(None, {}, ('+','id'), ('+', 'deadline')), | 511 ae(filt(None, {}, ('+','id'), ('+', 'deadline')), |
| 502 ['5', '2', '1', '3', '4']) | 512 ['5', '2', '1', '3', '4']) |
| 503 ae(filt(None, {}, ('-','id'), ('-', 'deadline')), | 513 ae(filt(None, {}, ('-','id'), ('-', 'deadline')), |
| 504 ['4', '3', '1', '2', '5']) | 514 ['4', '3', '1', '2', '5']) |
| 505 | 515 |
| 506 def testDateSortMultilink(self): | 516 def testDateSortMultilink(self): |
| 507 d1 = date.Date('.') | 517 d1 = date.Date('.') |
| 508 ae, filter, filter_iter = self.filteringSetup() | 518 ae, iiter = self.filteringSetup() |
| 509 nid = self.db.issue.create(title="nodeadline", status='1') | 519 nid = self.db.issue.create(title="nodeadline", status='1') |
| 510 self.db.commit() | 520 self.db.commit() |
| 511 ae(sorted(self.db.issue.get('1','nosy')), []) | 521 ae(sorted(self.db.issue.get('1','nosy')), []) |
| 512 ae(sorted(self.db.issue.get('2','nosy')), []) | 522 ae(sorted(self.db.issue.get('2','nosy')), []) |
| 513 ae(sorted(self.db.issue.get('3','nosy')), ['1','2']) | 523 ae(sorted(self.db.issue.get('3','nosy')), ['1','2']) |
| 516 ae(self.db.user.get('1','username'), 'admin') | 526 ae(self.db.user.get('1','username'), 'admin') |
| 517 ae(self.db.user.get('2','username'), 'fred') | 527 ae(self.db.user.get('2','username'), 'fred') |
| 518 ae(self.db.user.get('3','username'), 'bleep') | 528 ae(self.db.user.get('3','username'), 'bleep') |
| 519 # filter_iter currently doesn't work for Multilink sort | 529 # filter_iter currently doesn't work for Multilink sort |
| 520 # so testing only filter | 530 # so testing only filter |
| 521 ae(filter(None, {}, ('+', 'id'), ('+','nosy')), | 531 for f in iiter(): |
| 522 ['1', '2', '5', '4', '3']) | 532 if f.__name__ != 'filter': |
| 523 ae(filter(None, {}, ('+','deadline'), ('+', 'nosy')), | 533 continue |
| 524 ['5', '2', '1', '4', '3']) | 534 ae(f(None, {}, ('+', 'id'), ('+','nosy')), |
| 525 ae(filter(None, {}, ('+','nosy'), ('+', 'deadline')), | 535 ['1', '2', '5', '4', '3']) |
| 526 ['5', '2', '1', '3', '4']) | 536 ae(f(None, {}, ('+','deadline'), ('+', 'nosy')), |
| 537 ['5', '2', '1', '4', '3']) | |
| 538 ae(f(None, {}, ('+','nosy'), ('+', 'deadline')), | |
| 539 ['5', '2', '1', '3', '4']) | |
| 527 | 540 |
| 528 # Interval | 541 # Interval |
| 529 def testIntervalChange(self): | 542 def testIntervalChange(self): |
| 530 self.assertRaises(TypeError, self.db.issue.create, | 543 self.assertRaises(TypeError, self.db.issue.create, |
| 531 title='spam', foo=1) | 544 title='spam', foo=1) |
| 1563 got = self.db.issue.find(status={'1':1}) | 1576 got = self.db.issue.find(status={'1':1}) |
| 1564 got.sort() | 1577 got.sort() |
| 1565 self.assertEqual(got, [one, three]) | 1578 self.assertEqual(got, [one, three]) |
| 1566 | 1579 |
| 1567 def testFindRevLinkMultilink(self): | 1580 def testFindRevLinkMultilink(self): |
| 1568 ae, filter, filter_iter = self.filteringSetupTransitiveSearch('user') | 1581 ae, dummy = self.filteringSetupTransitiveSearch('user') |
| 1569 ni = 'nosy_issues' | 1582 ni = 'nosy_issues' |
| 1570 self.db.issue.set('6', nosy=['3', '4', '5']) | 1583 self.db.issue.set('6', nosy=['3', '4', '5']) |
| 1571 self.db.issue.set('7', nosy=['5']) | 1584 self.db.issue.set('7', nosy=['5']) |
| 1572 # After this setup we have the following values for nosy: | 1585 # After this setup we have the following values for nosy: |
| 1573 # issue assignedto nosy | 1586 # issue assignedto nosy |
| 1706 self.db.issue.create(**issue) | 1719 self.db.issue.create(**issue) |
| 1707 self.db.commit() | 1720 self.db.commit() |
| 1708 return self.iterSetup(classname) | 1721 return self.iterSetup(classname) |
| 1709 | 1722 |
| 1710 def testFilteringID(self): | 1723 def testFilteringID(self): |
| 1711 ae, filter, filter_iter = self.filteringSetup() | 1724 ae, iiter = self.filteringSetup() |
| 1712 for filt in filter, filter_iter: | 1725 for filt in iiter(): |
| 1713 ae(filt(None, {'id': '1'}, ('+','id'), (None,None)), ['1']) | 1726 ae(filt(None, {'id': '1'}, ('+','id'), (None,None)), ['1']) |
| 1714 ae(filt(None, {'id': '2'}, ('+','id'), (None,None)), ['2']) | 1727 ae(filt(None, {'id': '2'}, ('+','id'), (None,None)), ['2']) |
| 1715 ae(filt(None, {'id': '100'}, ('+','id'), (None,None)), []) | 1728 ae(filt(None, {'id': '100'}, ('+','id'), (None,None)), []) |
| 1716 | 1729 |
| 1717 def testFilteringBoolean(self): | 1730 def testFilteringBoolean(self): |
| 1718 ae, filter, filter_iter = self.filteringSetup('user') | 1731 ae, iiter = self.filteringSetup('user') |
| 1719 a = 'assignable' | 1732 a = 'assignable' |
| 1720 for filt in filter, filter_iter: | 1733 for filt in iiter(): |
| 1721 ae(filt(None, {a: '1'}, ('+','id'), (None,None)), ['3','4']) | 1734 ae(filt(None, {a: '1'}, ('+','id'), (None,None)), ['3','4']) |
| 1722 ae(filt(None, {a: '0'}, ('+','id'), (None,None)), ['5']) | 1735 ae(filt(None, {a: '0'}, ('+','id'), (None,None)), ['5']) |
| 1723 ae(filt(None, {a: ['1']}, ('+','id'), (None,None)), ['3','4']) | 1736 ae(filt(None, {a: ['1']}, ('+','id'), (None,None)), ['3','4']) |
| 1724 ae(filt(None, {a: ['0']}, ('+','id'), (None,None)), ['5']) | 1737 ae(filt(None, {a: ['0']}, ('+','id'), (None,None)), ['5']) |
| 1725 ae(filt(None, {a: ['0','1']}, ('+','id'), (None,None)), | 1738 ae(filt(None, {a: ['0','1']}, ('+','id'), (None,None)), |
| 1741 ae(filt(None, {a: [False]}, ('+','id'), (None,None)), ['5']) | 1754 ae(filt(None, {a: [False]}, ('+','id'), (None,None)), ['5']) |
| 1742 ae(filt(None, {a: [False,True]}, ('+','id'), (None,None)), | 1755 ae(filt(None, {a: [False,True]}, ('+','id'), (None,None)), |
| 1743 ['3','4','5']) | 1756 ['3','4','5']) |
| 1744 | 1757 |
| 1745 def testFilteringNumber(self): | 1758 def testFilteringNumber(self): |
| 1746 ae, filter, filter_iter = self.filteringSetup('user') | 1759 ae, iiter = self.filteringSetup('user') |
| 1747 for filt in filter, filter_iter: | 1760 for filt in iiter(): |
| 1748 ae(filt(None, {'age': '1'}, ('+','id'), (None,None)), ['3']) | 1761 ae(filt(None, {'age': '1'}, ('+','id'), (None,None)), ['3']) |
| 1749 ae(filt(None, {'age': '1.5'}, ('+','id'), (None,None)), ['4']) | 1762 ae(filt(None, {'age': '1.5'}, ('+','id'), (None,None)), ['4']) |
| 1750 ae(filt(None, {'age': '2'}, ('+','id'), (None,None)), ['5']) | 1763 ae(filt(None, {'age': '2'}, ('+','id'), (None,None)), ['5']) |
| 1751 ae(filt(None, {'age': ['1','2']}, ('+','id'), (None,None)), | 1764 ae(filt(None, {'age': ['1','2']}, ('+','id'), (None,None)), |
| 1752 ['3','5']) | 1765 ['3','5']) |
| 1753 ae(filt(None, {'age': 2}, ('+','id'), (None,None)), ['5']) | 1766 ae(filt(None, {'age': 2}, ('+','id'), (None,None)), ['5']) |
| 1754 ae(filt(None, {'age': [1,2]}, ('+','id'), (None,None)), ['3','5']) | 1767 ae(filt(None, {'age': [1,2]}, ('+','id'), (None,None)), ['3','5']) |
| 1755 | 1768 |
| 1756 def testFilteringString(self): | 1769 def testFilteringString(self): |
| 1757 ae, filter, filter_iter = self.filteringSetup() | 1770 ae, iiter = self.filteringSetup() |
| 1758 for filt in filter, filter_iter: | 1771 for filt in iiter(): |
| 1759 ae(filt(None, {'title': ['one']}, ('+','id'), (None,None)), ['1']) | 1772 ae(filt(None, {'title': ['one']}, ('+','id'), (None,None)), ['1']) |
| 1760 ae(filt(None, {'title': ['issue one']}, ('+','id'), (None,None)), | 1773 ae(filt(None, {'title': ['issue one']}, ('+','id'), (None,None)), |
| 1761 ['1']) | 1774 ['1']) |
| 1762 ae(filt(None, {'title': ['issue', 'one']}, ('+','id'), (None,None)), | 1775 ae(filt(None, {'title': ['issue', 'one']}, ('+','id'), (None,None)), |
| 1763 ['1']) | 1776 ['1']) |
| 1769 def testFilteringStringCase(self): | 1782 def testFilteringStringCase(self): |
| 1770 """ | 1783 """ |
| 1771 Similar to testFilteringString except the search parameters | 1784 Similar to testFilteringString except the search parameters |
| 1772 have different capitalization. | 1785 have different capitalization. |
| 1773 """ | 1786 """ |
| 1774 ae, filter, filter_iter = self.filteringSetup() | 1787 ae, iiter = self.filteringSetup() |
| 1775 for filt in filter, filter_iter: | 1788 for filt in iiter(): |
| 1776 ae(filt(None, {'title': ['One']}, ('+','id'), (None,None)), ['1']) | 1789 ae(filt(None, {'title': ['One']}, ('+','id'), (None,None)), ['1']) |
| 1777 ae(filt(None, {'title': ['Issue One']}, ('+','id'), (None,None)), | 1790 ae(filt(None, {'title': ['Issue One']}, ('+','id'), (None,None)), |
| 1778 ['1']) | 1791 ['1']) |
| 1779 ae(filt(None, {'title': ['ISSUE', 'ONE']}, ('+','id'), (None,None)), | 1792 ae(filt(None, {'title': ['ISSUE', 'ONE']}, ('+','id'), (None,None)), |
| 1780 ['1']) | 1793 ['1']) |
| 1782 ['1','2','3']) | 1795 ['1','2','3']) |
| 1783 ae(filt(None, {'title': ['One', 'Two']}, ('+','id'), (None,None)), | 1796 ae(filt(None, {'title': ['One', 'Two']}, ('+','id'), (None,None)), |
| 1784 []) | 1797 []) |
| 1785 | 1798 |
| 1786 def testFilteringStringExactMatch(self): | 1799 def testFilteringStringExactMatch(self): |
| 1787 ae, filter, filter_iter = self.filteringSetup() | 1800 ae, iiter = self.filteringSetup() |
| 1788 # Change title of issue2 to 'issue' so we can test substring | 1801 # Change title of issue2 to 'issue' so we can test substring |
| 1789 # search vs exact search | 1802 # search vs exact search |
| 1790 self.db.issue.set('2', title='issue') | 1803 self.db.issue.set('2', title='issue') |
| 1791 #self.db.commit() | 1804 #self.db.commit() |
| 1792 for filt in filter, filter_iter: | 1805 for filt in iiter(): |
| 1793 ae(filt(None, {}, exact_match_spec = | 1806 ae(filt(None, {}, exact_match_spec = |
| 1794 {'title': ['one']}), []) | 1807 {'title': ['one']}), []) |
| 1795 ae(filt(None, {}, exact_match_spec = | 1808 ae(filt(None, {}, exact_match_spec = |
| 1796 {'title': ['issue one']}), ['1']) | 1809 {'title': ['issue one']}), ['1']) |
| 1797 ae(filt(None, {}, exact_match_spec = | 1810 ae(filt(None, {}, exact_match_spec = |
| 1818 | 1831 |
| 1819 def testFilteringSpecialChars(self): | 1832 def testFilteringSpecialChars(self): |
| 1820 """ Special characters in SQL search are '%' and '_', some used | 1833 """ Special characters in SQL search are '%' and '_', some used |
| 1821 to lead to a traceback. | 1834 to lead to a traceback. |
| 1822 """ | 1835 """ |
| 1823 ae, filter, filter_iter = self.filteringSetup() | 1836 ae, iiter = self.filteringSetup() |
| 1824 self.db.issue.set('1', title="With % symbol") | 1837 self.db.issue.set('1', title="With % symbol") |
| 1825 self.db.issue.set('2', title="With _ symbol") | 1838 self.db.issue.set('2', title="With _ symbol") |
| 1826 self.db.issue.set('3', title="With \\ symbol") | 1839 self.db.issue.set('3', title="With \\ symbol") |
| 1827 self.db.issue.set('4', title="With ' symbol") | 1840 self.db.issue.set('4', title="With ' symbol") |
| 1828 d = dict (status = '1') | 1841 d = dict (status = '1') |
| 1829 for filt in filter, filter_iter: | 1842 for filt in iiter(): |
| 1830 ae(filt(None, dict(title='%'), ('+','id'), (None,None)), ['1']) | 1843 ae(filt(None, dict(title='%'), ('+','id'), (None,None)), ['1']) |
| 1831 ae(filt(None, dict(title='_'), ('+','id'), (None,None)), ['2']) | 1844 ae(filt(None, dict(title='_'), ('+','id'), (None,None)), ['2']) |
| 1832 ae(filt(None, dict(title='\\'), ('+','id'), (None,None)), ['3']) | 1845 ae(filt(None, dict(title='\\'), ('+','id'), (None,None)), ['3']) |
| 1833 ae(filt(None, dict(title="'"), ('+','id'), (None,None)), ['4']) | 1846 ae(filt(None, dict(title="'"), ('+','id'), (None,None)), ['4']) |
| 1834 | 1847 |
| 1835 def testFilteringLink(self): | 1848 def testFilteringLink(self): |
| 1836 ae, filter, filter_iter = self.filteringSetup() | 1849 ae, iiter = self.filteringSetup() |
| 1837 a = 'assignedto' | 1850 a = 'assignedto' |
| 1838 grp = (None, None) | 1851 grp = (None, None) |
| 1839 for filt in filter, filter_iter: | 1852 for filt in iiter(): |
| 1840 ae(filt(None, {'status': '1'}, ('+','id'), grp), ['2','3']) | 1853 ae(filt(None, {'status': '1'}, ('+','id'), grp), ['2','3']) |
| 1841 ae(filt(None, {a: '-1'}, ('+','id'), grp), ['3','4']) | 1854 ae(filt(None, {a: '-1'}, ('+','id'), grp), ['3','4']) |
| 1842 ae(filt(None, {a: None}, ('+','id'), grp), ['3','4']) | 1855 ae(filt(None, {a: None}, ('+','id'), grp), ['3','4']) |
| 1843 ae(filt(None, {a: [None]}, ('+','id'), grp), ['3','4']) | 1856 ae(filt(None, {a: [None]}, ('+','id'), grp), ['3','4']) |
| 1844 ae(filt(None, {a: ['-1', None]}, ('+','id'), grp), ['3','4']) | 1857 ae(filt(None, {a: ['-1', None]}, ('+','id'), grp), ['3','4']) |
| 1845 ae(filt(None, {a: ['1', None]}, ('+','id'), grp), ['1', '3','4']) | 1858 ae(filt(None, {a: ['1', None]}, ('+','id'), grp), ['1', '3','4']) |
| 1846 | 1859 |
| 1847 def testFilteringRevLink(self): | 1860 def testFilteringRevLink(self): |
| 1848 ae, filter, filter_iter = self.filteringSetupTransitiveSearch('user') | 1861 ae, iiter = self.filteringSetupTransitiveSearch('user') |
| 1849 # We have | 1862 # We have |
| 1850 # issue assignedto | 1863 # issue assignedto |
| 1851 # 1: 6 | 1864 # 1: 6 |
| 1852 # 2: 6 | 1865 # 2: 6 |
| 1853 # 3: 7 | 1866 # 3: 7 |
| 1854 # 4: 8 | 1867 # 4: 8 |
| 1855 # 5: 9 | 1868 # 5: 9 |
| 1856 # 6: 10 | 1869 # 6: 10 |
| 1857 # 7: 10 | 1870 # 7: 10 |
| 1858 # 8: 10 | 1871 # 8: 10 |
| 1859 for filt in filter, filter_iter: | 1872 for filt in iiter(): |
| 1860 ae(filt(None, {'issues': ['3', '4']}), ['7', '8']) | 1873 ae(filt(None, {'issues': ['3', '4']}), ['7', '8']) |
| 1861 ae(filt(None, {'issues': ['1', '4', '8']}), ['6', '8', '10']) | 1874 ae(filt(None, {'issues': ['1', '4', '8']}), ['6', '8', '10']) |
| 1862 ae(filt(None, {'issues.title': ['ts2']}), ['6']) | 1875 ae(filt(None, {'issues.title': ['ts2']}), ['6']) |
| 1863 ae(filt(None, {'issues': ['-1']}), ['1', '2', '3', '4', '5']) | 1876 ae(filt(None, {'issues': ['-1']}), ['1', '2', '3', '4', '5']) |
| 1864 ae(filt(None, {'issues': '-1'}), ['1', '2', '3', '4', '5']) | 1877 ae(filt(None, {'issues': '-1'}), ['1', '2', '3', '4', '5']) |
| 1872 # Now retire some linked-to issues and retry | 1885 # Now retire some linked-to issues and retry |
| 1873 self.db.issue.retire('6') | 1886 self.db.issue.retire('6') |
| 1874 self.db.issue.retire('2') | 1887 self.db.issue.retire('2') |
| 1875 self.db.issue.retire('3') | 1888 self.db.issue.retire('3') |
| 1876 self.db.commit() | 1889 self.db.commit() |
| 1877 for filt in filter, filter_iter: | 1890 for filt in iiter(): |
| 1878 ae(filt(None, {'issues': ['3', '4']}), ['8']) | 1891 ae(filt(None, {'issues': ['3', '4']}), ['8']) |
| 1879 ae(filt(None, {'issues': ['1', '4', '8']}), ['6', '8', '10']) | 1892 ae(filt(None, {'issues': ['1', '4', '8']}), ['6', '8', '10']) |
| 1880 ae(filt(None, {'issues.title': ['ts2']}), []) | 1893 ae(filt(None, {'issues.title': ['ts2']}), []) |
| 1881 ae(filt(None, {'issues': ['-1']}), ['1', '2', '3', '4', '5', '7']) | 1894 ae(filt(None, {'issues': ['-1']}), ['1', '2', '3', '4', '5', '7']) |
| 1882 ae(filt(None, {'issues': '-1'}), ['1', '2', '3', '4', '5', '7']) | 1895 ae(filt(None, {'issues': '-1'}), ['1', '2', '3', '4', '5', '7']) |
| 1883 self.assertEqual(ls(self.db.user.get('6', 'issues')), ['1']) | 1896 self.assertEqual(ls(self.db.user.get('6', 'issues')), ['1']) |
| 1884 self.assertEqual(ls(self.db.user.get('7', 'issues')), []) | 1897 self.assertEqual(ls(self.db.user.get('7', 'issues')), []) |
| 1885 self.assertEqual(ls(self.db.user.get('10', 'issues')), ['7', '8']) | 1898 self.assertEqual(ls(self.db.user.get('10', 'issues')), ['7', '8']) |
| 1886 | 1899 |
| 1887 def testFilteringLinkSortSearchMultilink(self): | 1900 def testFilteringLinkSortSearchMultilink(self): |
| 1888 ae, filter, filter_iter = self.filteringSetup() | 1901 ae, iiter = self.filteringSetup() |
| 1889 a = 'assignedto' | 1902 a = 'assignedto' |
| 1890 grp = (None, None) | 1903 grp = (None, None) |
| 1891 for filt in filter, filter_iter: | 1904 for filt in iiter(): |
| 1892 ae(filt(None, {'status.mls': '1'}, ('+','status')), ['2','3']) | 1905 ae(filt(None, {'status.mls': '1'}, ('+','status')), ['2','3']) |
| 1893 ae(filt(None, {'status.mls': '2'}, ('+','status')), ['2','3']) | 1906 ae(filt(None, {'status.mls': '2'}, ('+','status')), ['2','3']) |
| 1894 | 1907 |
| 1895 def testFilteringMultilinkAndGroup(self): | 1908 def testFilteringMultilinkAndGroup(self): |
| 1896 """testFilteringMultilinkAndGroup: | 1909 """testFilteringMultilinkAndGroup: |
| 1897 See roundup Bug 1541128: apparently grouping by something and | 1910 See roundup Bug 1541128: apparently grouping by something and |
| 1898 searching a Multilink failed with MySQL 5.0 | 1911 searching a Multilink failed with MySQL 5.0 |
| 1899 """ | 1912 """ |
| 1900 ae, filter, filter_iter = self.filteringSetup() | 1913 ae, iiter = self.filteringSetup() |
| 1901 for f in filter, filter_iter: | 1914 for f in iiter(): |
| 1902 ae(f(None, {'files': '1'}, ('-','activity'), ('+','status')), ['4']) | 1915 ae(f(None, {'files': '1'}, ('-','activity'), ('+','status')), ['4']) |
| 1903 | 1916 |
| 1904 def testFilteringRetired(self): | 1917 def testFilteringRetired(self): |
| 1905 ae, filter, filter_iter = self.filteringSetup() | 1918 ae, iiter = self.filteringSetup() |
| 1906 self.db.issue.retire('2') | 1919 self.db.issue.retire('2') |
| 1907 for f in filter, filter_iter: | 1920 for f in iiter(): |
| 1908 ae(f(None, {'status': '1'}, ('+','id'), (None,None)), ['3']) | 1921 ae(f(None, {'status': '1'}, ('+','id'), (None,None)), ['3']) |
| 1909 | 1922 |
| 1910 def testFilteringMultilink(self): | 1923 def testFilteringMultilink(self): |
| 1911 ae, filter, filter_iter = self.filteringSetup() | 1924 ae, iiter = self.filteringSetup() |
| 1912 for filt in filter, filter_iter: | 1925 for filt in iiter(): |
| 1913 ae(filt(None, {'nosy': '3'}, ('+','id'), (None,None)), ['4']) | 1926 ae(filt(None, {'nosy': '3'}, ('+','id'), (None,None)), ['4']) |
| 1914 ae(filt(None, {'nosy': '-1'}, ('+','id'), (None,None)), ['1', '2']) | 1927 ae(filt(None, {'nosy': '-1'}, ('+','id'), (None,None)), ['1', '2']) |
| 1915 ae(filt(None, {'nosy': ['1','2']}, ('+', 'status'), | 1928 ae(filt(None, {'nosy': ['1','2']}, ('+', 'status'), |
| 1916 ('-', 'deadline')), ['4', '3']) | 1929 ('-', 'deadline')), ['4', '3']) |
| 1917 | 1930 |
| 1918 def testFilteringRevMultilink(self): | 1931 def testFilteringRevMultilink(self): |
| 1919 ae, filter, filter_iter = self.filteringSetupTransitiveSearch('user') | 1932 ae, iiter = self.filteringSetupTransitiveSearch('user') |
| 1920 ni = 'nosy_issues' | 1933 ni = 'nosy_issues' |
| 1921 self.db.issue.set('6', nosy=['3', '4', '5']) | 1934 self.db.issue.set('6', nosy=['3', '4', '5']) |
| 1922 self.db.issue.set('7', nosy=['5']) | 1935 self.db.issue.set('7', nosy=['5']) |
| 1923 # After this setup we have the following values for nosy: | 1936 # After this setup we have the following values for nosy: |
| 1924 # issue nosy | 1937 # issue nosy |
| 1928 # 4: | 1941 # 4: |
| 1929 # 5: | 1942 # 5: |
| 1930 # 6: 3, 4, 5 | 1943 # 6: 3, 4, 5 |
| 1931 # 7: 5 | 1944 # 7: 5 |
| 1932 # 8: | 1945 # 8: |
| 1933 for filt in filter, filter_iter: | 1946 for filt in iiter(): |
| 1934 ae(filt(None, {ni: ['1', '2']}), ['4', '5']) | 1947 ae(filt(None, {ni: ['1', '2']}), ['4', '5']) |
| 1935 ae(filt(None, {ni: ['6','7']}), ['3', '4', '5']) | 1948 ae(filt(None, {ni: ['6','7']}), ['3', '4', '5']) |
| 1936 ae(filt(None, {'nosy_issues.title': ['ts2']}), ['5']) | 1949 ae(filt(None, {'nosy_issues.title': ['ts2']}), ['5']) |
| 1937 ae(filt(None, {ni: ['-1']}), ['1', '2', '6', '7', '8', '9', '10']) | 1950 ae(filt(None, {ni: ['-1']}), ['1', '2', '6', '7', '8', '9', '10']) |
| 1938 ae(filt(None, {ni: '-1'}), ['1', '2', '6', '7', '8', '9', '10']) | 1951 ae(filt(None, {ni: '-1'}), ['1', '2', '6', '7', '8', '9', '10']) |
| 1944 self.assertEqual(ls(n.nosy_issues), ['1', '6']) | 1957 self.assertEqual(ls(n.nosy_issues), ['1', '6']) |
| 1945 # Now retire some linked-to issues and retry | 1958 # Now retire some linked-to issues and retry |
| 1946 self.db.issue.retire('2') | 1959 self.db.issue.retire('2') |
| 1947 self.db.issue.retire('6') | 1960 self.db.issue.retire('6') |
| 1948 self.db.commit() | 1961 self.db.commit() |
| 1949 for filt in filter, filter_iter: | 1962 for filt in iiter(): |
| 1950 ae(filt(None, {ni: ['1', '2']}), ['4']) | 1963 ae(filt(None, {ni: ['1', '2']}), ['4']) |
| 1951 ae(filt(None, {ni: ['6','7']}), ['5']) | 1964 ae(filt(None, {ni: ['6','7']}), ['5']) |
| 1952 ae(filt(None, {'nosy_issues.title': ['ts2']}), []) | 1965 ae(filt(None, {'nosy_issues.title': ['ts2']}), []) |
| 1953 ae(filt(None, {ni: ['-1']}), | 1966 ae(filt(None, {ni: ['-1']}), |
| 1954 ['1', '2', '3', '6', '7', '8', '9', '10']) | 1967 ['1', '2', '3', '6', '7', '8', '9', '10']) |
| 1956 ['1', '2', '3', '6', '7', '8', '9', '10']) | 1969 ['1', '2', '3', '6', '7', '8', '9', '10']) |
| 1957 self.assertEqual(ls(self.db.user.get('4', ni)), ['1']) | 1970 self.assertEqual(ls(self.db.user.get('4', ni)), ['1']) |
| 1958 self.assertEqual(ls(self.db.user.get('5', ni)), ['7']) | 1971 self.assertEqual(ls(self.db.user.get('5', ni)), ['7']) |
| 1959 | 1972 |
| 1960 def testFilteringMany(self): | 1973 def testFilteringMany(self): |
| 1961 ae, filter, filter_iter = self.filteringSetup() | 1974 ae, iiter = self.filteringSetup() |
| 1962 for f in filter, filter_iter: | 1975 for f in iiter(): |
| 1963 ae(f(None, {'nosy': '2', 'status': '1'}, ('+','id'), (None,None)), | 1976 ae(f(None, {'nosy': '2', 'status': '1'}, ('+','id'), (None,None)), |
| 1964 ['3']) | 1977 ['3']) |
| 1965 | 1978 |
| 1966 def testFilteringRangeBasic(self): | 1979 def testFilteringRangeBasic(self): |
| 1967 ae, filter, filter_iter = self.filteringSetup() | 1980 ae, iiter = self.filteringSetup() |
| 1968 d = 'deadline' | 1981 d = 'deadline' |
| 1969 for f in filter, filter_iter: | 1982 for f in iiter(): |
| 1970 ae(f(None, {d: 'from 2003-02-10 to 2003-02-23'}), ['1','3']) | 1983 ae(f(None, {d: 'from 2003-02-10 to 2003-02-23'}), ['1','3']) |
| 1971 ae(f(None, {d: '2003-02-10; 2003-02-23'}), ['1','3']) | 1984 ae(f(None, {d: '2003-02-10; 2003-02-23'}), ['1','3']) |
| 1972 ae(f(None, {d: '; 2003-02-16'}), ['2']) | 1985 ae(f(None, {d: '; 2003-02-16'}), ['2']) |
| 1973 | 1986 |
| 1974 def testFilteringRangeTwoSyntaxes(self): | 1987 def testFilteringRangeTwoSyntaxes(self): |
| 1975 ae, filter, filter_iter = self.filteringSetup() | 1988 ae, iiter = self.filteringSetup() |
| 1976 for filt in filter, filter_iter: | 1989 for filt in iiter(): |
| 1977 ae(filt(None, {'deadline': 'from 2003-02-16'}), ['1', '3', '4']) | 1990 ae(filt(None, {'deadline': 'from 2003-02-16'}), ['1', '3', '4']) |
| 1978 ae(filt(None, {'deadline': '2003-02-16;'}), ['1', '3', '4']) | 1991 ae(filt(None, {'deadline': '2003-02-16;'}), ['1', '3', '4']) |
| 1979 | 1992 |
| 1980 def testFilteringRangeYearMonthDay(self): | 1993 def testFilteringRangeYearMonthDay(self): |
| 1981 ae, filter, filter_iter = self.filteringSetup() | 1994 ae, iiter = self.filteringSetup() |
| 1982 for filt in filter, filter_iter: | 1995 for filt in iiter(): |
| 1983 ae(filt(None, {'deadline': '2002'}), []) | 1996 ae(filt(None, {'deadline': '2002'}), []) |
| 1984 ae(filt(None, {'deadline': '2003'}), ['1', '2', '3']) | 1997 ae(filt(None, {'deadline': '2003'}), ['1', '2', '3']) |
| 1985 ae(filt(None, {'deadline': '2004'}), ['4']) | 1998 ae(filt(None, {'deadline': '2004'}), ['4']) |
| 1986 ae(filt(None, {'deadline': '2003-02-16'}), ['1']) | 1999 ae(filt(None, {'deadline': '2003-02-16'}), ['1']) |
| 1987 ae(filt(None, {'deadline': '2003-02-17'}), []) | 2000 ae(filt(None, {'deadline': '2003-02-17'}), []) |
| 1988 | 2001 |
| 1989 def testFilteringRangeMonths(self): | 2002 def testFilteringRangeMonths(self): |
| 1990 ae, filter, filter_iter = self.filteringSetup() | 2003 ae, iiter = self.filteringSetup() |
| 1991 for month in range(1, 13): | 2004 for month in range(1, 13): |
| 1992 for n in range(1, month+1): | 2005 for n in range(1, month+1): |
| 1993 i = self.db.issue.create(title='%d.%d'%(month, n), | 2006 i = self.db.issue.create(title='%d.%d'%(month, n), |
| 1994 deadline=date.Date('2001-%02d-%02d.00:00'%(month, n))) | 2007 deadline=date.Date('2001-%02d-%02d.00:00'%(month, n))) |
| 1995 self.db.commit() | 2008 self.db.commit() |
| 1996 | 2009 |
| 1997 for month in range(1, 13): | 2010 for month in range(1, 13): |
| 1998 for filt in filter, filter_iter: | 2011 for filt in iiter(): |
| 1999 r = filt(None, dict(deadline='2001-%02d'%month)) | 2012 r = filt(None, dict(deadline='2001-%02d'%month)) |
| 2000 assert len(r) == month, 'month %d != length %d'%(month, len(r)) | 2013 assert len(r) == month, 'month %d != length %d'%(month, len(r)) |
| 2001 | 2014 |
| 2002 def testFilteringDateRangeMulti(self): | 2015 def testFilteringDateRangeMulti(self): |
| 2003 ae, filter, filter_iter = self.filteringSetup() | 2016 ae, iiter = self.filteringSetup() |
| 2004 self.db.issue.create(title='no deadline') | 2017 self.db.issue.create(title='no deadline') |
| 2005 self.db.commit() | 2018 self.db.commit() |
| 2006 for filt in filter, filter_iter: | 2019 for filt in iiter(): |
| 2007 r = filt (None, dict(deadline='-')) | 2020 r = filt (None, dict(deadline='-')) |
| 2008 self.assertEqual(r, ['5']) | 2021 self.assertEqual(r, ['5']) |
| 2009 r = filt (None, dict(deadline=';2003-02-01,2004;')) | 2022 r = filt (None, dict(deadline=';2003-02-01,2004;')) |
| 2010 self.assertEqual(r, ['2', '4']) | 2023 self.assertEqual(r, ['2', '4']) |
| 2011 r = filt (None, dict(deadline='-,;2003-02-01,2004;')) | 2024 r = filt (None, dict(deadline='-,;2003-02-01,2004;')) |
| 2012 self.assertEqual(r, ['2', '4', '5']) | 2025 self.assertEqual(r, ['2', '4', '5']) |
| 2013 | 2026 |
| 2014 def testFilteringRangeInterval(self): | 2027 def testFilteringRangeInterval(self): |
| 2015 ae, filter, filter_iter = self.filteringSetup() | 2028 ae, iiter = self.filteringSetup() |
| 2016 for filt in filter, filter_iter: | 2029 for filt in iiter(): |
| 2017 ae(filt(None, {'foo': 'from 0:50 to 2:00'}), ['1']) | 2030 ae(filt(None, {'foo': 'from 0:50 to 2:00'}), ['1']) |
| 2018 ae(filt(None, {'foo': 'from 0:50 to 1d 2:00'}), ['1', '2']) | 2031 ae(filt(None, {'foo': 'from 0:50 to 1d 2:00'}), ['1', '2']) |
| 2019 ae(filt(None, {'foo': 'from 5:50'}), ['2']) | 2032 ae(filt(None, {'foo': 'from 5:50'}), ['2']) |
| 2020 ae(filt(None, {'foo': 'to 0:05'}), []) | 2033 ae(filt(None, {'foo': 'to 0:05'}), []) |
| 2021 | 2034 |
| 2022 def testFilteringRangeGeekInterval(self): | 2035 def testFilteringRangeGeekInterval(self): |
| 2023 ae, filter, filter_iter = self.filteringSetup() | 2036 ae, iiter = self.filteringSetup() |
| 2024 # Note: When querying, create date one minute later than the | 2037 # Note: When querying, create date one minute later than the |
| 2025 # timespan later queried to avoid race conditions where the | 2038 # timespan later queried to avoid race conditions where the |
| 2026 # creation of the deadline is more than a second ago when | 2039 # creation of the deadline is more than a second ago when |
| 2027 # queried -- in that case we wouldn't get the expected result. | 2040 # queried -- in that case we wouldn't get the expected result. |
| 2028 # By extending the interval by a minute we would need a very | 2041 # By extending the interval by a minute we would need a very |
| 2031 { 'deadline': date.Date('. -2d') + date.Interval ('00:01')}, | 2044 { 'deadline': date.Date('. -2d') + date.Interval ('00:01')}, |
| 2032 { 'deadline': date.Date('. -1d') + date.Interval ('00:01')}, | 2045 { 'deadline': date.Date('. -1d') + date.Interval ('00:01')}, |
| 2033 { 'deadline': date.Date('. -8d') + date.Interval ('00:01')}, | 2046 { 'deadline': date.Date('. -8d') + date.Interval ('00:01')}, |
| 2034 ): | 2047 ): |
| 2035 self.db.issue.create(**issue) | 2048 self.db.issue.create(**issue) |
| 2036 for filt in filter, filter_iter: | 2049 for filt in iiter(): |
| 2037 ae(filt(None, {'deadline': '-2d;'}), ['5', '6']) | 2050 ae(filt(None, {'deadline': '-2d;'}), ['5', '6']) |
| 2038 ae(filt(None, {'deadline': '-1d;'}), ['6']) | 2051 ae(filt(None, {'deadline': '-1d;'}), ['6']) |
| 2039 ae(filt(None, {'deadline': '-1w;'}), ['5', '6']) | 2052 ae(filt(None, {'deadline': '-1w;'}), ['5', '6']) |
| 2040 ae(filt(None, {'deadline': '. -2d;'}), ['5', '6']) | 2053 ae(filt(None, {'deadline': '. -2d;'}), ['5', '6']) |
| 2041 ae(filt(None, {'deadline': '. -1d;'}), ['6']) | 2054 ae(filt(None, {'deadline': '. -1d;'}), ['6']) |
| 2044 def testFilteringIntervalSort(self): | 2057 def testFilteringIntervalSort(self): |
| 2045 # 1: '1:10' | 2058 # 1: '1:10' |
| 2046 # 2: '1d' | 2059 # 2: '1d' |
| 2047 # 3: None | 2060 # 3: None |
| 2048 # 4: '0:10' | 2061 # 4: '0:10' |
| 2049 ae, filter, filter_iter = self.filteringSetup() | 2062 ae, iiter = self.filteringSetup() |
| 2050 for filt in filter, filter_iter: | 2063 for filt in iiter(): |
| 2051 # ascending should sort None, 1:10, 1d | 2064 # ascending should sort None, 1:10, 1d |
| 2052 ae(filt(None, {}, ('+','foo'), (None,None)), ['3', '4', '1', '2']) | 2065 ae(filt(None, {}, ('+','foo'), (None,None)), ['3', '4', '1', '2']) |
| 2053 # descending should sort 1d, 1:10, None | 2066 # descending should sort 1d, 1:10, None |
| 2054 ae(filt(None, {}, ('-','foo'), (None,None)), ['2', '1', '4', '3']) | 2067 ae(filt(None, {}, ('-','foo'), (None,None)), ['2', '1', '4', '3']) |
| 2055 | 2068 |
| 2056 def testFilteringStringSort(self): | 2069 def testFilteringStringSort(self): |
| 2057 # 1: 'issue one' | 2070 # 1: 'issue one' |
| 2058 # 2: 'issue two' | 2071 # 2: 'issue two' |
| 2059 # 3: 'issue three' | 2072 # 3: 'issue three' |
| 2060 # 4: 'non four' | 2073 # 4: 'non four' |
| 2061 ae, filter, filter_iter = self.filteringSetup() | 2074 ae, iiter = self.filteringSetup() |
| 2062 for filt in filter, filter_iter: | 2075 for filt in iiter(): |
| 2063 ae(filt(None, {}, ('+','title')), ['1', '3', '2', '4']) | 2076 ae(filt(None, {}, ('+','title')), ['1', '3', '2', '4']) |
| 2064 ae(filt(None, {}, ('-','title')), ['4', '2', '3', '1']) | 2077 ae(filt(None, {}, ('-','title')), ['4', '2', '3', '1']) |
| 2065 # Test string case: For now allow both, w/wo case matching. | 2078 # Test string case: For now allow both, w/wo case matching. |
| 2066 # 1: 'issue one' | 2079 # 1: 'issue one' |
| 2067 # 2: 'issue two' | 2080 # 2: 'issue two' |
| 2068 # 3: 'Issue three' | 2081 # 3: 'Issue three' |
| 2069 # 4: 'non four' | 2082 # 4: 'non four' |
| 2070 self.db.issue.set('3', title='Issue three') | 2083 self.db.issue.set('3', title='Issue three') |
| 2071 for filt in filter, filter_iter: | 2084 for filt in iiter(): |
| 2072 ae(filt(None, {}, ('+','title')), ['1', '3', '2', '4']) | 2085 ae(filt(None, {}, ('+','title')), ['1', '3', '2', '4']) |
| 2073 ae(filt(None, {}, ('-','title')), ['4', '2', '3', '1']) | 2086 ae(filt(None, {}, ('-','title')), ['4', '2', '3', '1']) |
| 2074 # Obscure bug in anydbm backend trying to convert to number | 2087 # Obscure bug in anydbm backend trying to convert to number |
| 2075 # 1: '1st issue' | 2088 # 1: '1st issue' |
| 2076 # 2: '2' | 2089 # 2: '2' |
| 2077 # 3: 'Issue three' | 2090 # 3: 'Issue three' |
| 2078 # 4: 'non four' | 2091 # 4: 'non four' |
| 2079 self.db.issue.set('1', title='1st issue') | 2092 self.db.issue.set('1', title='1st issue') |
| 2080 self.db.issue.set('2', title='2') | 2093 self.db.issue.set('2', title='2') |
| 2081 for filt in filter, filter_iter: | 2094 for filt in iiter(): |
| 2082 ae(filt(None, {}, ('+','title')), ['1', '2', '3', '4']) | 2095 ae(filt(None, {}, ('+','title')), ['1', '2', '3', '4']) |
| 2083 ae(filt(None, {}, ('-','title')), ['4', '3', '2', '1']) | 2096 ae(filt(None, {}, ('-','title')), ['4', '3', '2', '1']) |
| 2084 | 2097 |
| 2085 def testFilteringMultilinkSort(self): | 2098 def testFilteringMultilinkSort(self): |
| 2086 # 1: [] Reverse: 1: [] | 2099 # 1: [] Reverse: 1: [] |
| 2090 # Note the sort order for the multilink doen't change when | 2103 # Note the sort order for the multilink doen't change when |
| 2091 # reversing the sort direction due to the re-sorting of the | 2104 # reversing the sort direction due to the re-sorting of the |
| 2092 # multilink! | 2105 # multilink! |
| 2093 # Note that we don't test filter_iter here, Multilink sort-order | 2106 # Note that we don't test filter_iter here, Multilink sort-order |
| 2094 # isn't defined for that. | 2107 # isn't defined for that. |
| 2095 ae, filt, dummy = self.filteringSetup() | 2108 ae, iiter = self.filteringSetup() |
| 2096 ae(filt(None, {}, ('+','nosy'), (None,None)), ['1', '2', '4', '3']) | 2109 for filt in iiter(): |
| 2097 ae(filt(None, {}, ('-','nosy'), (None,None)), ['4', '3', '1', '2']) | 2110 if filt.__name__ != 'filter': |
| 2111 continue | |
| 2112 ae(filt(None, {}, ('+','nosy'), (None,None)), ['1', '2', '4', '3']) | |
| 2113 ae(filt(None, {}, ('-','nosy'), (None,None)), ['4', '3', '1', '2']) | |
| 2098 | 2114 |
| 2099 def testFilteringMultilinkSortGroup(self): | 2115 def testFilteringMultilinkSortGroup(self): |
| 2100 # 1: status: 2 "in-progress" nosy: [] | 2116 # 1: status: 2 "in-progress" nosy: [] |
| 2101 # 2: status: 1 "unread" nosy: [] | 2117 # 2: status: 1 "unread" nosy: [] |
| 2102 # 3: status: 1 "unread" nosy: ['admin','fred'] | 2118 # 3: status: 1 "unread" nosy: ['admin','fred'] |
| 2103 # 4: status: 3 "testing" nosy: ['admin','bleep','fred'] | 2119 # 4: status: 3 "testing" nosy: ['admin','bleep','fred'] |
| 2104 # Note that we don't test filter_iter here, Multilink sort-order | 2120 # Note that we don't test filter_iter here, Multilink sort-order |
| 2105 # isn't defined for that. | 2121 # isn't defined for that. |
| 2106 ae, filt, dummy = self.filteringSetup() | 2122 ae, iiter = self.filteringSetup() |
| 2107 ae(filt(None, {}, ('+','nosy'), ('+','status')), ['1', '4', '2', '3']) | 2123 for filt in iiter(): |
| 2108 ae(filt(None, {}, ('-','nosy'), ('+','status')), ['1', '4', '3', '2']) | 2124 if filt.__name__ != 'filter': |
| 2109 ae(filt(None, {}, ('+','nosy'), ('-','status')), ['2', '3', '4', '1']) | 2125 continue |
| 2110 ae(filt(None, {}, ('-','nosy'), ('-','status')), ['3', '2', '4', '1']) | 2126 ae(filt(None, {}, ('+','nosy'), ('+','status')), |
| 2111 ae(filt(None, {}, ('+','status'), ('+','nosy')), ['1', '2', '4', '3']) | 2127 ['1', '4', '2', '3']) |
| 2112 ae(filt(None, {}, ('-','status'), ('+','nosy')), ['2', '1', '4', '3']) | 2128 ae(filt(None, {}, ('-','nosy'), ('+','status')), |
| 2113 ae(filt(None, {}, ('+','status'), ('-','nosy')), ['4', '3', '1', '2']) | 2129 ['1', '4', '3', '2']) |
| 2114 ae(filt(None, {}, ('-','status'), ('-','nosy')), ['4', '3', '2', '1']) | 2130 ae(filt(None, {}, ('+','nosy'), ('-','status')), |
| 2131 ['2', '3', '4', '1']) | |
| 2132 ae(filt(None, {}, ('-','nosy'), ('-','status')), | |
| 2133 ['3', '2', '4', '1']) | |
| 2134 ae(filt(None, {}, ('+','status'), ('+','nosy')), | |
| 2135 ['1', '2', '4', '3']) | |
| 2136 ae(filt(None, {}, ('-','status'), ('+','nosy')), | |
| 2137 ['2', '1', '4', '3']) | |
| 2138 ae(filt(None, {}, ('+','status'), ('-','nosy')), | |
| 2139 ['4', '3', '1', '2']) | |
| 2140 ae(filt(None, {}, ('-','status'), ('-','nosy')), | |
| 2141 ['4', '3', '2', '1']) | |
| 2115 | 2142 |
| 2116 def testFilteringLinkSortGroup(self): | 2143 def testFilteringLinkSortGroup(self): |
| 2117 # 1: status: 2 -> 'i', priority: 3 -> 1 | 2144 # 1: status: 2 -> 'i', priority: 3 -> 1 |
| 2118 # 2: status: 1 -> 'u', priority: 3 -> 1 | 2145 # 2: status: 1 -> 'u', priority: 3 -> 1 |
| 2119 # 3: status: 1 -> 'u', priority: 2 -> 3 | 2146 # 3: status: 1 -> 'u', priority: 2 -> 3 |
| 2120 # 4: status: 3 -> 't', priority: 2 -> 3 | 2147 # 4: status: 3 -> 't', priority: 2 -> 3 |
| 2121 ae, filter, filter_iter = self.filteringSetup() | 2148 ae, iiter = self.filteringSetup() |
| 2122 for filt in filter, filter_iter: | 2149 for filt in iiter(): |
| 2123 ae(filt(None, {}, ('+','status'), ('+','priority')), | 2150 ae(filt(None, {}, ('+','status'), ('+','priority')), |
| 2124 ['1', '2', '4', '3']) | 2151 ['1', '2', '4', '3']) |
| 2125 ae(filt(None, {'priority':'2'}, ('+','status'), ('+','priority')), | 2152 ae(filt(None, {'priority':'2'}, ('+','status'), ('+','priority')), |
| 2126 ['4', '3']) | 2153 ['4', '3']) |
| 2127 ae(filt(None, {'priority.order':'3'}, ('+','status'), | 2154 ae(filt(None, {'priority.order':'3'}, ('+','status'), |
| 2134 def testFilteringDateSort(self): | 2161 def testFilteringDateSort(self): |
| 2135 # '1': '2003-02-16.22:50' | 2162 # '1': '2003-02-16.22:50' |
| 2136 # '2': '2003-01-01.00:00' | 2163 # '2': '2003-01-01.00:00' |
| 2137 # '3': '2003-02-18' | 2164 # '3': '2003-02-18' |
| 2138 # '4': '2004-03-08' | 2165 # '4': '2004-03-08' |
| 2139 ae, filter, filter_iter = self.filteringSetup() | 2166 ae, iiter = self.filteringSetup() |
| 2140 for f in filter, filter_iter: | 2167 for f in iiter(): |
| 2141 # ascending | 2168 # ascending |
| 2142 ae(f(None, {}, ('+','deadline'), (None,None)), ['2', '1', '3', '4']) | 2169 ae(f(None, {}, ('+','deadline'), (None,None)), ['2', '1', '3', '4']) |
| 2143 # descending | 2170 # descending |
| 2144 ae(f(None, {}, ('-','deadline'), (None,None)), ['4', '3', '1', '2']) | 2171 ae(f(None, {}, ('-','deadline'), (None,None)), ['4', '3', '1', '2']) |
| 2145 | 2172 |
| 2146 def testFilteringDateSortPriorityGroup(self): | 2173 def testFilteringDateSortPriorityGroup(self): |
| 2147 # '1': '2003-02-16.22:50' 1 => 2 | 2174 # '1': '2003-02-16.22:50' 1 => 2 |
| 2148 # '2': '2003-01-01.00:00' 3 => 1 | 2175 # '2': '2003-01-01.00:00' 3 => 1 |
| 2149 # '3': '2003-02-18' 2 => 3 | 2176 # '3': '2003-02-18' 2 => 3 |
| 2150 # '4': '2004-03-08' 1 => 2 | 2177 # '4': '2004-03-08' 1 => 2 |
| 2151 ae, filter, filter_iter = self.filteringSetup() | 2178 ae, iiter = self.filteringSetup() |
| 2152 | 2179 |
| 2153 for filt in filter, filter_iter: | 2180 for filt in iiter(): |
| 2154 # ascending | 2181 # ascending |
| 2155 ae(filt(None, {}, ('+','deadline'), ('+','priority')), | 2182 ae(filt(None, {}, ('+','deadline'), ('+','priority')), |
| 2156 ['2', '1', '3', '4']) | 2183 ['2', '1', '3', '4']) |
| 2157 ae(filt(None, {}, ('-','deadline'), ('+','priority')), | 2184 ae(filt(None, {}, ('-','deadline'), ('+','priority')), |
| 2158 ['1', '2', '4', '3']) | 2185 ['1', '2', '4', '3']) |
| 2161 ['3', '4', '2', '1']) | 2188 ['3', '4', '2', '1']) |
| 2162 ae(filt(None, {}, ('-','deadline'), ('-','priority')), | 2189 ae(filt(None, {}, ('-','deadline'), ('-','priority')), |
| 2163 ['4', '3', '1', '2']) | 2190 ['4', '3', '1', '2']) |
| 2164 | 2191 |
| 2165 def testFilteringTransitiveLinkUser(self): | 2192 def testFilteringTransitiveLinkUser(self): |
| 2166 ae, filter, filter_iter = self.filteringSetupTransitiveSearch('user') | 2193 ae, iiter = self.filteringSetupTransitiveSearch('user') |
| 2167 for f in filter, filter_iter: | 2194 for f in iiter(): |
| 2168 ae(f(None, {'supervisor.username': 'ceo'}, ('+','username')), | 2195 ae(f(None, {'supervisor.username': 'ceo'}, ('+','username')), |
| 2169 ['4', '5']) | 2196 ['4', '5']) |
| 2170 ae(f(None, {'supervisor.supervisor.username': 'ceo'}, | 2197 ae(f(None, {'supervisor.supervisor.username': 'ceo'}, |
| 2171 ('+','username')), ['6', '7', '8', '9', '10']) | 2198 ('+','username')), ['6', '7', '8', '9', '10']) |
| 2172 ae(f(None, {'supervisor.supervisor': '3'}, ('+','username')), | 2199 ae(f(None, {'supervisor.supervisor': '3'}, ('+','username')), |
| 2182 ['8', '9', '10']) | 2209 ['8', '9', '10']) |
| 2183 ae(f(None, {'supervisor.supervisor': '3', 'supervisor': '4'}, | 2210 ae(f(None, {'supervisor.supervisor': '3', 'supervisor': '4'}, |
| 2184 ('+','username')), ['6', '7']) | 2211 ('+','username')), ['6', '7']) |
| 2185 | 2212 |
| 2186 def testFilteringTransitiveLinkUserLimit(self): | 2213 def testFilteringTransitiveLinkUserLimit(self): |
| 2187 ae, filter, filter_iter = self.filteringSetupTransitiveSearch('user') | 2214 ae, iiter = self.filteringSetupTransitiveSearch('user') |
| 2188 for f in filter, filter_iter: | 2215 for f in iiter(): |
| 2189 ae(f(None, {'supervisor.username': 'ceo'}, ('+','username'), | 2216 ae(f(None, {'supervisor.username': 'ceo'}, ('+','username'), |
| 2190 limit=1), ['4']) | 2217 limit=1), ['4']) |
| 2191 ae(f(None, {'supervisor.supervisor.username': 'ceo'}, | 2218 ae(f(None, {'supervisor.supervisor.username': 'ceo'}, |
| 2192 ('+','username'), limit=4), ['6', '7', '8', '9']) | 2219 ('+','username'), limit=4), ['6', '7', '8', '9']) |
| 2193 ae(f(None, {'supervisor.supervisor': '3'}, ('+','username'), | 2220 ae(f(None, {'supervisor.supervisor': '3'}, ('+','username'), |
| 2201 limit=4, offset=3), []) | 2228 limit=4, offset=3), []) |
| 2202 ae(f(None, {'supervisor.supervisor': '3', 'supervisor': '4'}, | 2229 ae(f(None, {'supervisor.supervisor': '3', 'supervisor': '4'}, |
| 2203 ('+','username'), limit=1, offset=5), []) | 2230 ('+','username'), limit=1, offset=5), []) |
| 2204 | 2231 |
| 2205 def testFilteringTransitiveLinkSort(self): | 2232 def testFilteringTransitiveLinkSort(self): |
| 2206 ae, filter, filter_iter = self.filteringSetupTransitiveSearch() | 2233 ae, iiter = self.filteringSetupTransitiveSearch() |
| 2207 ae, ufilter, ufilter_iter = self.iterSetup('user') | 2234 ae, uiter = self.iterSetup('user') |
| 2208 # Need to make ceo his own (and first two users') supervisor, | 2235 # Need to make ceo his own (and first two users') supervisor, |
| 2209 # otherwise we will depend on sorting order of NULL values. | 2236 # otherwise we will depend on sorting order of NULL values. |
| 2210 # Leave that to a separate test. | 2237 # Leave that to a separate test. |
| 2211 self.db.user.set('1', supervisor = '3') | 2238 self.db.user.set('1', supervisor = '3') |
| 2212 self.db.user.set('2', supervisor = '3') | 2239 self.db.user.set('2', supervisor = '3') |
| 2213 self.db.user.set('3', supervisor = '3') | 2240 self.db.user.set('3', supervisor = '3') |
| 2214 for ufilt in ufilter, ufilter_iter: | 2241 for ufilt in uiter(): |
| 2215 ae(ufilt(None, {'supervisor':'3'}, []), ['1', '2', '3', '4', '5']) | 2242 ae(ufilt(None, {'supervisor':'3'}, []), ['1', '2', '3', '4', '5']) |
| 2216 ae(ufilt(None, {}, [('+','supervisor.supervisor.supervisor'), | 2243 ae(ufilt(None, {}, [('+','supervisor.supervisor.supervisor'), |
| 2217 ('+','supervisor.supervisor'), ('+','supervisor'), | 2244 ('+','supervisor.supervisor'), ('+','supervisor'), |
| 2218 ('+','username')]), | 2245 ('+','username')]), |
| 2219 ['1', '3', '2', '4', '5', '6', '7', '8', '9', '10']) | 2246 ['1', '3', '2', '4', '5', '6', '7', '8', '9', '10']) |
| 2220 ae(ufilt(None, {}, [('+','supervisor.supervisor.supervisor'), | 2247 ae(ufilt(None, {}, [('+','supervisor.supervisor.supervisor'), |
| 2221 ('-','supervisor.supervisor'), ('-','supervisor'), | 2248 ('-','supervisor.supervisor'), ('-','supervisor'), |
| 2222 ('+','username')]), | 2249 ('+','username')]), |
| 2223 ['8', '9', '10', '6', '7', '1', '3', '2', '4', '5']) | 2250 ['8', '9', '10', '6', '7', '1', '3', '2', '4', '5']) |
| 2224 for f in filter, filter_iter: | 2251 for f in iiter(): |
| 2225 ae(f(None, {}, [('+','assignedto.supervisor.supervisor.supervisor'), | 2252 ae(f(None, {}, [('+','assignedto.supervisor.supervisor.supervisor'), |
| 2226 ('+','assignedto.supervisor.supervisor'), | 2253 ('+','assignedto.supervisor.supervisor'), |
| 2227 ('+','assignedto.supervisor'), ('+','assignedto')]), | 2254 ('+','assignedto.supervisor'), ('+','assignedto')]), |
| 2228 ['1', '2', '3', '4', '5', '6', '7', '8']) | 2255 ['1', '2', '3', '4', '5', '6', '7', '8']) |
| 2229 ae(f(None, {}, [('+','assignedto.supervisor.supervisor.supervisor'), | 2256 ae(f(None, {}, [('+','assignedto.supervisor.supervisor.supervisor'), |
| 2255 ('-','assignedto.supervisor'), ('+','assignedto'), | 2282 ('-','assignedto.supervisor'), ('+','assignedto'), |
| 2256 ('+','status')]), ['4', '5', '1', '2', '3']) | 2283 ('+','status')]), ['4', '5', '1', '2', '3']) |
| 2257 | 2284 |
| 2258 def testFilteringTransitiveLinkSortNull(self): | 2285 def testFilteringTransitiveLinkSortNull(self): |
| 2259 """Check sorting of NULL values""" | 2286 """Check sorting of NULL values""" |
| 2260 ae, filter, filter_iter = self.filteringSetupTransitiveSearch() | 2287 ae, iiter = self.filteringSetupTransitiveSearch() |
| 2261 ae, ufilter, ufilter_iter = self.iterSetup('user') | 2288 ae, uiter = self.iterSetup('user') |
| 2262 for ufilt in ufilter, ufilter_iter: | 2289 for ufilt in uiter(): |
| 2263 ae(ufilt(None, {}, [('+','supervisor.supervisor.supervisor'), | 2290 ae(ufilt(None, {}, [('+','supervisor.supervisor.supervisor'), |
| 2264 ('+','supervisor.supervisor'), ('+','supervisor'), | 2291 ('+','supervisor.supervisor'), ('+','supervisor'), |
| 2265 ('+','username')]), | 2292 ('+','username')]), |
| 2266 ['1', '3', '2', '4', '5', '6', '7', '8', '9', '10']) | 2293 ['1', '3', '2', '4', '5', '6', '7', '8', '9', '10']) |
| 2267 ae(ufilt(None, {}, [('+','supervisor.supervisor.supervisor'), | 2294 ae(ufilt(None, {}, [('+','supervisor.supervisor.supervisor'), |
| 2268 ('-','supervisor.supervisor'), ('-','supervisor'), | 2295 ('-','supervisor.supervisor'), ('-','supervisor'), |
| 2269 ('+','username')]), | 2296 ('+','username')]), |
| 2270 ['8', '9', '10', '6', '7', '4', '5', '1', '3', '2']) | 2297 ['8', '9', '10', '6', '7', '4', '5', '1', '3', '2']) |
| 2271 for f in filter, filter_iter: | 2298 for f in iiter(): |
| 2272 ae(f(None, {}, [('+','assignedto.supervisor.supervisor.supervisor'), | 2299 ae(f(None, {}, [('+','assignedto.supervisor.supervisor.supervisor'), |
| 2273 ('+','assignedto.supervisor.supervisor'), | 2300 ('+','assignedto.supervisor.supervisor'), |
| 2274 ('+','assignedto.supervisor'), ('+','assignedto')]), | 2301 ('+','assignedto.supervisor'), ('+','assignedto')]), |
| 2275 ['1', '2', '3', '4', '5', '6', '7', '8']) | 2302 ['1', '2', '3', '4', '5', '6', '7', '8']) |
| 2276 ae(f(None, {}, [('+','assignedto.supervisor.supervisor.supervisor'), | 2303 ae(f(None, {}, [('+','assignedto.supervisor.supervisor.supervisor'), |
| 2277 ('+','assignedto.supervisor.supervisor'), | 2304 ('+','assignedto.supervisor.supervisor'), |
| 2278 ('-','assignedto.supervisor'), ('+','assignedto')]), | 2305 ('-','assignedto.supervisor'), ('+','assignedto')]), |
| 2279 ['4', '5', '6', '7', '8', '1', '2', '3']) | 2306 ['4', '5', '6', '7', '8', '1', '2', '3']) |
| 2280 | 2307 |
| 2281 def testFilteringTransitiveLinkIssue(self): | 2308 def testFilteringTransitiveLinkIssue(self): |
| 2282 ae, filter, filter_iter = self.filteringSetupTransitiveSearch() | 2309 ae, iiter = self.filteringSetupTransitiveSearch() |
| 2283 for filt in filter, filter_iter: | 2310 for filt in iiter(): |
| 2284 ae(filt(None, {'assignedto.supervisor.username': 'grouplead1'}, | 2311 ae(filt(None, {'assignedto.supervisor.username': 'grouplead1'}, |
| 2285 ('+','id')), ['1', '2', '3']) | 2312 ('+','id')), ['1', '2', '3']) |
| 2286 ae(filt(None, {'assignedto.supervisor.username': 'grouplead2'}, | 2313 ae(filt(None, {'assignedto.supervisor.username': 'grouplead2'}, |
| 2287 ('+','id')), ['4', '5', '6', '7', '8']) | 2314 ('+','id')), ['4', '5', '6', '7', '8']) |
| 2288 ae(filt(None, {'assignedto.supervisor.username': 'grouplead2', | 2315 ae(filt(None, {'assignedto.supervisor.username': 'grouplead2', |
| 2293 'status': '2'}, ('+','id')), ['5', '7']) | 2320 'status': '2'}, ('+','id')), ['5', '7']) |
| 2294 ae(filt(None, {'assignedto.supervisor': ['4', '5'], 'status': '2'}, | 2321 ae(filt(None, {'assignedto.supervisor': ['4', '5'], 'status': '2'}, |
| 2295 ('+','id')), ['1', '3', '5', '7']) | 2322 ('+','id')), ['1', '3', '5', '7']) |
| 2296 | 2323 |
| 2297 def testFilteringTransitiveMultilink(self): | 2324 def testFilteringTransitiveMultilink(self): |
| 2298 ae, filter, filter_iter = self.filteringSetupTransitiveSearch() | 2325 ae, iiter = self.filteringSetupTransitiveSearch() |
| 2299 for filt in filter, filter_iter: | 2326 for filt in iiter(): |
| 2300 ae(filt(None, {'messages.author.username': 'grouplead1'}, | 2327 ae(filt(None, {'messages.author.username': 'grouplead1'}, |
| 2301 ('+','id')), []) | 2328 ('+','id')), []) |
| 2302 ae(filt(None, {'messages.author': '6'}, | 2329 ae(filt(None, {'messages.author': '6'}, |
| 2303 ('+','id')), ['1', '2']) | 2330 ('+','id')), ['1', '2']) |
| 2304 ae(filt(None, {'messages.author.id': '6'}, | 2331 ae(filt(None, {'messages.author.id': '6'}, |
| 2330 'messages': ['5', '7']}, ('+','id')), ['5', '8']) | 2357 'messages': ['5', '7']}, ('+','id')), ['5', '8']) |
| 2331 | 2358 |
| 2332 def testFilteringTransitiveMultilinkSort(self): | 2359 def testFilteringTransitiveMultilinkSort(self): |
| 2333 # Note that we don't test filter_iter here, Multilink sort-order | 2360 # Note that we don't test filter_iter here, Multilink sort-order |
| 2334 # isn't defined for that. | 2361 # isn't defined for that. |
| 2335 ae, filt, dummy = self.filteringSetupTransitiveSearch() | 2362 ae, iiter = self.filteringSetupTransitiveSearch() |
| 2336 ae(filt(None, {}, [('+','messages.author')]), | 2363 for filt in iiter(): |
| 2337 ['1', '2', '3', '4', '5', '8', '6', '7']) | 2364 if filt.__name__ != 'filter': |
| 2338 ae(filt(None, {}, [('-','messages.author')]), | 2365 continue |
| 2339 ['8', '6', '7', '5', '4', '3', '1', '2']) | 2366 ae(filt(None, {}, [('+','messages.author')]), |
| 2340 ae(filt(None, {}, [('+','messages.date')]), | 2367 ['1', '2', '3', '4', '5', '8', '6', '7']) |
| 2341 ['6', '7', '8', '5', '4', '3', '1', '2']) | 2368 ae(filt(None, {}, [('-','messages.author')]), |
| 2342 ae(filt(None, {}, [('-','messages.date')]), | 2369 ['8', '6', '7', '5', '4', '3', '1', '2']) |
| 2343 ['1', '2', '3', '4', '8', '5', '6', '7']) | 2370 ae(filt(None, {}, [('+','messages.date')]), |
| 2344 ae(filt(None, {}, [('+','messages.author'),('+','messages.date')]), | 2371 ['6', '7', '8', '5', '4', '3', '1', '2']) |
| 2345 ['1', '2', '3', '4', '5', '8', '6', '7']) | 2372 ae(filt(None, {}, [('-','messages.date')]), |
| 2346 ae(filt(None, {}, [('-','messages.author'),('+','messages.date')]), | 2373 ['1', '2', '3', '4', '8', '5', '6', '7']) |
| 2347 ['8', '6', '7', '5', '4', '3', '1', '2']) | 2374 ae(filt(None, {}, [('+','messages.author'),('+','messages.date')]), |
| 2348 ae(filt(None, {}, [('+','messages.author'),('-','messages.date')]), | 2375 ['1', '2', '3', '4', '5', '8', '6', '7']) |
| 2349 ['1', '2', '3', '4', '5', '8', '6', '7']) | 2376 ae(filt(None, {}, [('-','messages.author'),('+','messages.date')]), |
| 2350 ae(filt(None, {}, [('-','messages.author'),('-','messages.date')]), | 2377 ['8', '6', '7', '5', '4', '3', '1', '2']) |
| 2351 ['8', '6', '7', '5', '4', '3', '1', '2']) | 2378 ae(filt(None, {}, [('+','messages.author'),('-','messages.date')]), |
| 2352 ae(filt(None, {}, [('+','messages.author'),('+','assignedto')]), | 2379 ['1', '2', '3', '4', '5', '8', '6', '7']) |
| 2353 ['1', '2', '3', '4', '5', '8', '6', '7']) | 2380 ae(filt(None, {}, [('-','messages.author'),('-','messages.date')]), |
| 2354 ae(filt(None, {}, [('+','messages.author'), | 2381 ['8', '6', '7', '5', '4', '3', '1', '2']) |
| 2355 ('-','assignedto.supervisor'),('-','assignedto')]), | 2382 ae(filt(None, {}, [('+','messages.author'),('+','assignedto')]), |
| 2356 ['1', '2', '3', '4', '5', '8', '6', '7']) | 2383 ['1', '2', '3', '4', '5', '8', '6', '7']) |
| 2357 ae(filt(None, {}, | 2384 ae(filt(None, {}, [('+','messages.author'), |
| 2358 [('+','messages.author.supervisor.supervisor.supervisor'), | 2385 ('-','assignedto.supervisor'),('-','assignedto')]), |
| 2359 ('+','messages.author.supervisor.supervisor'), | 2386 ['1', '2', '3', '4', '5', '8', '6', '7']) |
| 2360 ('+','messages.author.supervisor'), ('+','messages.author')]), | 2387 ae(filt(None, {}, |
| 2361 ['1', '2', '3', '4', '5', '6', '7', '8']) | 2388 [('+','messages.author.supervisor.supervisor.supervisor'), |
| 2389 ('+','messages.author.supervisor.supervisor'), | |
| 2390 ('+','messages.author.supervisor'), ('+','messages.author')]), | |
| 2391 ['1', '2', '3', '4', '5', '6', '7', '8']) | |
| 2362 self.db.user.setorderprop('age') | 2392 self.db.user.setorderprop('age') |
| 2363 self.db.msg.setorderprop('date') | 2393 self.db.msg.setorderprop('date') |
| 2364 ae(filt(None, {}, [('+','messages'), ('+','messages.author')]), | 2394 for filt in iiter(): |
| 2365 ['6', '7', '8', '5', '4', '3', '1', '2']) | 2395 if filt.__name__ != 'filter': |
| 2366 ae(filt(None, {}, [('+','messages.author'), ('+','messages')]), | 2396 continue |
| 2367 ['6', '7', '8', '5', '4', '3', '1', '2']) | 2397 ae(filt(None, {}, [('+','messages'), ('+','messages.author')]), |
| 2398 ['6', '7', '8', '5', '4', '3', '1', '2']) | |
| 2399 ae(filt(None, {}, [('+','messages.author'), ('+','messages')]), | |
| 2400 ['6', '7', '8', '5', '4', '3', '1', '2']) | |
| 2368 self.db.msg.setorderprop('author') | 2401 self.db.msg.setorderprop('author') |
| 2369 # Orderprop is a Link/Multilink: | 2402 for filt in iiter(): |
| 2370 # messages are sorted by orderprop().labelprop(), i.e. by | 2403 if filt.__name__ != 'filter': |
| 2371 # author.username, *not* by author.orderprop() (author.age)! | 2404 continue |
| 2372 ae(filt(None, {}, [('+','messages')]), | 2405 # Orderprop is a Link/Multilink: |
| 2373 ['1', '2', '3', '4', '5', '8', '6', '7']) | 2406 # messages are sorted by orderprop().labelprop(), i.e. by |
| 2374 ae(filt(None, {}, [('+','messages.author'), ('+','messages')]), | 2407 # author.username, *not* by author.orderprop() (author.age)! |
| 2375 ['6', '7', '8', '5', '4', '3', '1', '2']) | 2408 ae(filt(None, {}, [('+','messages')]), |
| 2376 # The following will sort by | 2409 ['1', '2', '3', '4', '5', '8', '6', '7']) |
| 2377 # author.supervisor.username and then by | 2410 ae(filt(None, {}, [('+','messages.author'), ('+','messages')]), |
| 2378 # author.username | 2411 ['6', '7', '8', '5', '4', '3', '1', '2']) |
| 2379 # I've resited the tempation to implement recursive orderprop | 2412 # The following will sort by |
| 2380 # here: There could even be loops if several classes specify a | 2413 # author.supervisor.username and then by |
| 2381 # Link or Multilink as the orderprop... | 2414 # author.username |
| 2382 # msg: 4: worker1 (id 5) : grouplead1 (id 4) ceo (id 3) | 2415 # I've resited the tempation to implement recursive orderprop |
| 2383 # msg: 5: worker2 (id 7) : grouplead1 (id 4) ceo (id 3) | 2416 # here: There could even be loops if several classes specify a |
| 2384 # msg: 6: worker3 (id 8) : grouplead2 (id 5) ceo (id 3) | 2417 # Link or Multilink as the orderprop... |
| 2385 # msg: 7: worker4 (id 9) : grouplead2 (id 5) ceo (id 3) | 2418 # msg: 4: worker1 (id 5) : grouplead1 (id 4) ceo (id 3) |
| 2386 # msg: 8: worker5 (id 10) : grouplead2 (id 5) ceo (id 3) | 2419 # msg: 5: worker2 (id 7) : grouplead1 (id 4) ceo (id 3) |
| 2387 # issue 1: messages 4 sortkey:[[grouplead1], [worker1], 1] | 2420 # msg: 6: worker3 (id 8) : grouplead2 (id 5) ceo (id 3) |
| 2388 # issue 2: messages 4 sortkey:[[grouplead1], [worker1], 2] | 2421 # msg: 7: worker4 (id 9) : grouplead2 (id 5) ceo (id 3) |
| 2389 # issue 3: messages 5 sortkey:[[grouplead1], [worker2], 3] | 2422 # msg: 8: worker5 (id 10) : grouplead2 (id 5) ceo (id 3) |
| 2390 # issue 4: messages 6 sortkey:[[grouplead2], [worker3], 4] | 2423 # issue 1: messages 4 sortkey:[[grouplead1], [worker1], 1] |
| 2391 # issue 5: messages 7 sortkey:[[grouplead2], [worker4], 5] | 2424 # issue 2: messages 4 sortkey:[[grouplead1], [worker1], 2] |
| 2392 # issue 6: messages 8 sortkey:[[grouplead2], [worker5], 6] | 2425 # issue 3: messages 5 sortkey:[[grouplead1], [worker2], 3] |
| 2393 # issue 7: messages 8 sortkey:[[grouplead2], [worker5], 7] | 2426 # issue 4: messages 6 sortkey:[[grouplead2], [worker3], 4] |
| 2394 # issue 8: messages 7,8 sortkey:[[grouplead2, grouplead2], ...] | 2427 # issue 5: messages 7 sortkey:[[grouplead2], [worker4], 5] |
| 2428 # issue 6: messages 8 sortkey:[[grouplead2], [worker5], 6] | |
| 2429 # issue 7: messages 8 sortkey:[[grouplead2], [worker5], 7] | |
| 2430 # issue 8: messages 7,8 sortkey:[[grouplead2, grouplead2], ...] | |
| 2395 self.db.user.setorderprop('supervisor') | 2431 self.db.user.setorderprop('supervisor') |
| 2396 ae(filt(None, {}, [('+','messages.author'), ('-','messages')]), | 2432 for filt in iiter(): |
| 2397 ['3', '1', '2', '6', '7', '5', '4', '8']) | 2433 if filt.__name__ != 'filter': |
| 2434 continue | |
| 2435 ae(filt(None, {}, [('+','messages.author'), ('-','messages')]), | |
| 2436 ['3', '1', '2', '6', '7', '5', '4', '8']) | |
| 2398 | 2437 |
| 2399 def testFilteringSortId(self): | 2438 def testFilteringSortId(self): |
| 2400 ae, filter, filter_iter = self.filteringSetupTransitiveSearch('user') | 2439 ae, iiter = self.filteringSetupTransitiveSearch('user') |
| 2401 for filt in filter, filter_iter: | 2440 for filt in iiter(): |
| 2402 ae(filt(None, {}, ('+','id')), | 2441 ae(filt(None, {}, ('+','id')), |
| 2403 ['1', '2', '3', '4', '5', '6', '7', '8', '9', '10']) | 2442 ['1', '2', '3', '4', '5', '6', '7', '8', '9', '10']) |
| 2404 | 2443 |
| 2405 def testFilteringRetiredString(self): | 2444 def testFilteringRetiredString(self): |
| 2406 ae, filter, filter_iter = self.filteringSetup() | 2445 ae, iiter = self.filteringSetup() |
| 2407 self.db.issue.retire('1') | 2446 self.db.issue.retire('1') |
| 2408 self.db.commit() | 2447 self.db.commit() |
| 2409 r = { None: (['1'], ['1'], ['1'], ['1', '2', '3'], []) | 2448 r = { None: (['1'], ['1'], ['1'], ['1', '2', '3'], []) |
| 2410 , True: (['1'], ['1'], ['1'], ['1'], []) | 2449 , True: (['1'], ['1'], ['1'], ['1'], []) |
| 2411 , False: ([], [], [], ['2', '3'], []) | 2450 , False: ([], [], [], ['2', '3'], []) |
| 2412 } | 2451 } |
| 2413 for filt in filter, filter_iter: | 2452 for filt in iiter(): |
| 2414 for retire in True, False, None: | 2453 for retire in True, False, None: |
| 2415 ae(filt(None, {'title': ['one']}, ('+','id'), | 2454 ae(filt(None, {'title': ['one']}, ('+','id'), |
| 2416 retired=retire), r[retire][0]) | 2455 retired=retire), r[retire][0]) |
| 2417 ae(filt(None, {'title': ['issue one']}, ('+','id'), | 2456 ae(filt(None, {'title': ['issue one']}, ('+','id'), |
| 2418 retired=retire), r[retire][1]) | 2457 retired=retire), r[retire][1]) |
| 2436 self.db = self.module.Database(config, 'admin') | 2475 self.db = self.module.Database(config, 'admin') |
| 2437 setupSchema(self.db, 0, self.module) | 2476 setupSchema(self.db, 0, self.module) |
| 2438 | 2477 |
| 2439 def testImportExport(self): | 2478 def testImportExport(self): |
| 2440 # use the filtering setup to create a bunch of items | 2479 # use the filtering setup to create a bunch of items |
| 2441 ae, dummy1, dummy2 = self.filteringSetup() | 2480 ae, dummy = self.filteringSetup() |
| 2442 # Get some stuff into the journal for testing import/export of | 2481 # Get some stuff into the journal for testing import/export of |
| 2443 # journal data: | 2482 # journal data: |
| 2444 self.db.user.set('4', password = password.Password('xyzzy')) | 2483 self.db.user.set('4', password = password.Password('xyzzy')) |
| 2445 self.db.user.set('4', age = 3) | 2484 self.db.user.set('4', age = 3) |
| 2446 self.db.user.set('4', assignable = True) | 2485 self.db.user.set('4', assignable = True) |
| 2549 # test import/export via admin interface | 2588 # test import/export via admin interface |
| 2550 def testAdminImportExport(self): | 2589 def testAdminImportExport(self): |
| 2551 import roundup.admin | 2590 import roundup.admin |
| 2552 import csv | 2591 import csv |
| 2553 # use the filtering setup to create a bunch of items | 2592 # use the filtering setup to create a bunch of items |
| 2554 ae, dummy1, dummy2 = self.filteringSetup() | 2593 ae, dummy = self.filteringSetup() |
| 2555 # create large field | 2594 # create large field |
| 2556 self.db.priority.create(name = 'X' * 500) | 2595 self.db.priority.create(name = 'X' * 500) |
| 2557 self.db.config.CSV_FIELD_SIZE = 400 | 2596 self.db.config.CSV_FIELD_SIZE = 400 |
| 2558 self.db.commit() | 2597 self.db.commit() |
| 2559 output = [] | 2598 output = [] |
| 2601 # test props from args parsing | 2640 # test props from args parsing |
| 2602 def testAdminOtherCommands(self): | 2641 def testAdminOtherCommands(self): |
| 2603 import roundup.admin | 2642 import roundup.admin |
| 2604 | 2643 |
| 2605 # use the filtering setup to create a bunch of items | 2644 # use the filtering setup to create a bunch of items |
| 2606 ae, dummy1, dummy2 = self.filteringSetup() | 2645 ae, dummy = self.filteringSetup() |
| 2607 # create large field | 2646 # create large field |
| 2608 self.db.priority.create(name = 'X' * 500) | 2647 self.db.priority.create(name = 'X' * 500) |
| 2609 self.db.config.CSV_FIELD_SIZE = 400 | 2648 self.db.config.CSV_FIELD_SIZE = 400 |
| 2610 self.db.commit() | 2649 self.db.commit() |
| 2611 | 2650 |
| 3226 self.assertEqual(self.db.sql_index_exists('_issue', '_issue_id_idx'), 1) | 3265 self.assertEqual(self.db.sql_index_exists('_issue', '_issue_id_idx'), 1) |
| 3227 self.assertEqual(self.db.sql_index_exists('_issue', '_issue_x_idx'), 0) | 3266 self.assertEqual(self.db.sql_index_exists('_issue', '_issue_x_idx'), 0) |
| 3228 | 3267 |
| 3229 class FilterCacheTest(commonDBTest): | 3268 class FilterCacheTest(commonDBTest): |
| 3230 def testFilteringTransitiveLinkCache(self): | 3269 def testFilteringTransitiveLinkCache(self): |
| 3231 ae, filter, filter_iter = self.filteringSetupTransitiveSearch() | 3270 ae, dummy = self.filteringSetupTransitiveSearch() |
| 3232 ae, ufilter, ufilter_iter = self.iterSetup('user') | 3271 ae, dummy = self.iterSetup('user') |
| 3233 # Need to make ceo his own (and first two users') supervisor | 3272 # Need to make ceo his own (and first two users') supervisor |
| 3234 self.db.user.set('1', supervisor = '3') | 3273 self.db.user.set('1', supervisor = '3') |
| 3235 self.db.user.set('2', supervisor = '3') | 3274 self.db.user.set('2', supervisor = '3') |
| 3236 self.db.user.set('3', supervisor = '3') | 3275 self.db.user.set('3', supervisor = '3') |
| 3237 # test bool value | 3276 # test bool value |
