11
2+ import os
3+
24from lmfdb .tests import LmfdbTest
35
46class HomePageTest (LmfdbTest ):
@@ -14,6 +16,21 @@ def test_genus(self):
1416 assert 'random' in homepage
1517 assert 'Gram' in homepage
1618
19+ def test_sidebar_submenu (self ):
20+ # Navigation between the lattice and genus index pages now lives in the
21+ # collapsible sidebar submenu (sidebar.yaml) instead of the old tab bar.
22+ # The Lattices sidebar entry has status beta, so it only renders when
23+ # the site runs in beta mode; BETA is re-read from the environment on
24+ # every request, so we can switch it on just for this test.
25+ os .environ ['BETA' ] = '1'
26+ try :
27+ for url in ("/Lattice/" , "/Lattice/Genus" ):
28+ homepage = self .tc .get (url ).get_data (as_text = True )
29+ assert 'href="/Lattice/">lattices</a>' in homepage
30+ assert 'href="/Lattice/Genus">genera</a>' in homepage
31+ finally :
32+ del os .environ ['BETA' ]
33+
1734 def test_lattice_rank (self ):
1835 L = self .tc .get ("/Lattice/9.9.8.001.76.1" ).get_data (as_text = True )
1936 assert '1.58740105196819947475170563927' in L #Hermite number
@@ -53,10 +70,56 @@ def test_lattice_search_next(self):
5370 assert '146' in L #search on the next page
5471
5572 def test_lattice_searchrank (self ):
56- # det constraint keeps the expected label on the first page of results
57- L = self .tc .get ("/Lattice/?rank=3&det=1000" ).get_data (as_text = True )
73+ # det constraint keeps the expected label on the first page of results.
74+ # 3.1.1000.3.3.3b.1 has determinant -1000, so with the sign-aware
75+ # determinant search it is only returned for det=-1000 (previously the
76+ # sign was ignored and det=1000 also matched it).
77+ L = self .tc .get ("/Lattice/?rank=3&det=-1000" ).get_data (as_text = True )
5878 assert '3.1.1000.3.3.3b.1' in L # rank search
5979
80+ def test_lattice_search_det_sign_positive (self ):
81+ # rank 3, det 5: exactly the two determinant +5 lattices, and none of
82+ # the determinant -5 lattices (the search is sign-aware)
83+ L = self .tc .get ("/Lattice/?rank=3&det=5" ).get_data (as_text = True )
84+ assert '3.3.5.77.1' in L
85+ assert '3.3.5.1f.1' in L
86+ assert '3.1.5.1b.1' not in L # det -5
87+ assert '3.1.5.73.1' not in L # det -5
88+
89+ def test_lattice_search_det_sign_negative (self ):
90+ # rank 3, det -5: exactly the two determinant -5 lattices, and none of
91+ # the determinant +5 lattices
92+ L = self .tc .get ("/Lattice/?rank=3&det=-5" ).get_data (as_text = True )
93+ assert '3.1.5.1b.1' in L
94+ assert '3.1.5.73.1' in L
95+ assert '3.3.5.77.1' not in L # det +5
96+ assert '3.3.5.1f.1' not in L # det +5
97+
98+ def test_lattice_search_det_range_positive (self ):
99+ # positive range: dets +5..+20 (81 rank-3 matches on devmirror), and no
100+ # negative-determinant lattice whose |det| lies in the range
101+ L = self .tc .get ("/Lattice/?rank=3&det=5-20&count=100" ).get_data (as_text = True )
102+ assert '3.3.5.77.1' in L # det 5
103+ assert '3.3.6.77.1' in L # det 6
104+ assert '3.1.7.2f.1' not in L # det -7
105+ assert '3.1.8.001.6.1' not in L # det -8
106+
107+ def test_lattice_search_det_range_negative (self ):
108+ # negative range: dets -20..-5 (71 rank-3 matches on devmirror), and no
109+ # positive-determinant lattice whose |det| lies in the range
110+ L = self .tc .get ("/Lattice/?rank=3&det=-20--5&count=100" ).get_data (as_text = True )
111+ assert '3.1.7.2f.1' in L # det -7
112+ assert '3.1.8.001.6.1' in L # det -8
113+ assert '3.3.5.77.1' not in L # det +5
114+ assert '3.3.6.77.1' not in L # det +6
115+
116+ def test_lattice_search_det_mixed_signs (self ):
117+ # a comma-separated list mixing signs is handled via an $or over
118+ # (det_sign, det_abs) clauses: det=5,-5 returns lattices of both signs
119+ L = self .tc .get ("/Lattice/?rank=3&det=5%2C-5&count=100" ).get_data (as_text = True )
120+ assert '3.3.5.77.1' in L # det +5
121+ assert '3.1.5.1b.1' in L # det -5
122+
60123 def test_lattice_searchlevel (self ):
61124 L = self .tc .get ("/Lattice/?start=&rank=&det=&level=90&gram=&minimum=&class_number=&aut_size=" ).get_data (as_text = True )
62125 assert '1.1.45.01.3b.1' in L #level search
@@ -135,12 +198,37 @@ def test_genus_searchGM(self):
135198 def test_lattice_searchGM_isometric (self ):
136199 # [5,7,7,16] is isometric to [5,2,2,7] (label 2.2.31.1.2) via basis change
137200 # U^T * [[5,2],[2,7]] * U with U = [[1,1],[0,1]]
138- # Not literally stored in the DB, so the genus+isometry postprocessor should find it
139- L = self .tc .get ("/Lattice/?gram=[5%2C7%2C7%2C16]&gram_format=full" ).get_data (as_text = True )
140- # The isometry search has a 20s wall-clock budget that includes the
141- # database queries; on a loaded runner it can fall back to the genus
142- # display or a plain results page before finding the isometric lattice
143- assert '2.2.31.1.2' in L or '2.2.31' in L or 'Integral lattices search results' in L
201+ # Not literally stored in the DB, so the genus+isometry postprocessor
202+ # MUST find the isometric lattice. The wall-clock budget includes the
203+ # database queries, so we raise it temporarily to make the test
204+ # deterministic on a loaded runner; the rank-2 computation itself is
205+ # fast (the time is dominated by the devmirror queries).
206+ from lmfdb .lattice import main as lattice_main
207+ old_limit = lattice_main .ISOM_TIME_LIMIT
208+ lattice_main .ISOM_TIME_LIMIT = 600.0
209+ try :
210+ L = self .tc .get ("/Lattice/?gram=[5%2C7%2C7%2C16]&gram_format=full" ).get_data (as_text = True )
211+ finally :
212+ lattice_main .ISOM_TIME_LIMIT = old_limit
213+ assert '2.2.31.1.2' in L
214+
215+ def test_lattice_searchGM_isometric_indefinite (self ):
216+ # Indefinite (signature (2,1), determinant -1) lattice 3.1.1.3.1 with
217+ # gram [[0,0,1],[0,1,0],[1,0,1]], transformed by the unimodular basis
218+ # change U = [[1,1,0],[0,1,0],[0,0,1]] into [[0,0,1],[0,1,1],[1,1,1]],
219+ # which is not stored in the DB. The genus lookup must find genus
220+ # 3.1.1.3 (class number 1, so the unique lattice is returned). This
221+ # exercises the nplus computation for indefinite input: nplus is
222+ # signature_pair()[0] = 2, not signature() = 2 - 1 = 1 (a bug formerly
223+ # masked by positive-definite lattices, where the two agree).
224+ from lmfdb .lattice import main as lattice_main
225+ old_limit = lattice_main .ISOM_TIME_LIMIT
226+ lattice_main .ISOM_TIME_LIMIT = 600.0
227+ try :
228+ L = self .tc .get ("/Lattice/?gram=[0%2C0%2C1%2C0%2C1%2C1%2C1%2C1%2C1]&gram_format=full" ).get_data (as_text = True )
229+ finally :
230+ lattice_main .ISOM_TIME_LIMIT = old_limit
231+ assert '3.1.1.3.1' in L
144232
145233 def test_lattice_searchGM_isometric_large_class_number (self ):
146234 # Rank-6 lattice in genus 6.6.311.61 (class_number=200)
@@ -158,14 +246,15 @@ def test_lattice_searchGM_isometric_large_class_number(self):
158246 U [0 ,1 ] = 1
159247 G2 = U .T * G * U
160248 gram = quote ('[' + ',' .join (str (x ) for x in G2 .list ()) + ']' )
161- L = self .tc .get ("/Lattice/?gram=%s&gram_format=full" % gram ).get_data (as_text = True )
162- # The isometry search has a 20s wall-clock budget that includes the
163- # database queries, so on a loaded runner any of three outcomes is
164- # legitimate: the exact lattice, its genus page, or a plain no-match
165- # results page. The deterministic rank-2 test above covers the
166- # isometry machinery itself; here we just require that the rank-6
167- # search completes without an error.
168- assert '6.6.311.61' in L or 'Integral lattices search results' in L
249+ response = self .tc .get ("/Lattice/?gram=%s&gram_format=full" % gram )
250+ # Smoke test only: with class number 200 the isometry scan usually hits
251+ # the default 20s time budget, and which fallback is reached depends on
252+ # timing. This test only checks that the endpoint survives the time
253+ # budget (HTTP 200, no traceback); the deterministic tests above pin
254+ # the isometry machinery itself.
255+ assert response .status_code == 200
256+ L = response .get_data (as_text = True )
257+ assert 'Traceback' not in L
169258
170259 #def test_latticeZ2(self):
171260 # L = self.tc.get("/Lattice/2.1.2.1.1").get_data(as_text=True)
0 commit comments