Related
I am new to SignalR and in the learning process, I am trying to make Stock ticker. I have over 1000 stocks list and want to show paging and update on real-time changes that's why I am using Groups with SignalR. Problem is that when I open page 1 then everything works fine until I open page 2, then page 1 stop getting signals and page 2 start getting signals. What am I missing here in SignalR groups? Please help me, Thanks.
Hub
[HubName("stockTicker")]
public class StockTickerHub : Hub
{
private StockTicker _stockTicker;
public StockTickerHub()
: this(StockTicker.Instance)
{
}
public StockTickerHub(StockTicker stockTicker)
{
_stockTicker = stockTicker;
}
public void OpenMarket()
{
var page = this.Context.QueryString["page_no"];
int pageno = Convert.ToInt32(page);
_stockTicker.OpenMarket(pageno);
tryAddGroup(page);
}
public Task tryAddGroup(string page)
{
return Groups.Add(Context.ConnectionId, page);
}
}
StockTicker.cs
public class StockTicker
{
MainModel _model = new MainModel();
private static Lazy<StockTicker> _instance = new Lazy<StockTicker>(() => new StockTicker(GlobalHost.ConnectionManager.GetHubContext<StockTickerHub>().Clients));
private TimeSpan _updateInterval = TimeSpan.FromMilliseconds(3000);
private Timer _timer;
public volatile int pageno;
private StockTicker(IHubConnectionContext<dynamic> clients)
{
Clients = clients;
}
public static StockTicker Instance
{
get
{
return _instance.Value;
}
}
private IHubConnectionContext<dynamic> Clients
{
get;
set;
}
public void OpenMarket(int page_no)
{
pageno = page_no;
_timer = new Timer(UpdateStockPrices, pageno, _updateInterval, _updateInterval);
}
private void UpdateStockPrices(object state)
{
var latest_stocks = new List<StockViewModel>();
latest_stocks = _model.Get100Stocks(pageno);
foreach (var stock in latest_stocks)
{
BroadcastStockPrice(stock, pageno);
}
}
private void BroadcastStockPrice(StockViewModel stock, int pageno)
{
Clients.Group(pageno.ToString()).updateStockPrice(stock);
//Clients.All.updateStockPrice(stock);
}
}
(Updated Question)
StockTicker.js
if (!String.prototype.supplant) {
String.prototype.supplant = function (o) {
return this.replace(/{([^{}]*)}/g,
function (a, b) {
var r = o[b];
return typeof r === 'string' || typeof r === 'number' ? r : a;
}
);
};
}
jQuery.fn.flash = function (color, duration) {
var current = this.css('backgroundColor');
this.animate({ backgroundColor: 'rgb(' + color + ')' }, duration / 2)
.animate({ backgroundColor: current }, duration / 2);
};
$(function () {
var ticker = $.connection.stockTicker;
var $stockTable = $('#stockTable');
var $stockTableBody = $stockTable.find('tbody');
tdPrice = '<td data-rank-price="{currency_query}" data-sort="{currency_price_usd}"><div data-price-spn="{currency_query}">${currency_price_usd}</div></td>';
tdPercentage = '<td data-rank-perc="{currency_query}" data-sort="{currency_change_24h_usd}"><div data-change-spn="{currency_query}"><span class="{DirectionClass}">{currency_change_24h_usd}</span></div></td>';
tdVolume = '<td data-rank-volume="{currency_query}" data-sort="{currency_24h_volume_usd}"><div data-24-volume-spn="{currency_query}>${currency_24h_volume_usd}</div></td>';
tdMarketcap = '<td data-rank-cap="{currency_query}" data-sort="{currency_market_cap_usd}"><div data-mcap-spn="{currency_query}">${currency_market_cap_usd}</div></td>';
function formatStock(stock) {
return $.extend(stock, {
currency_price_usd: formatprices(stock.currency_price_usd),
currency_change_24h_usd: stock.currency_change_24h_usd == null ? '0.00%' : (stock.currency_change_24h_usd).toFixed(2) + '%',
currency_24h_volume_usd: stock.currency_24h_volume_usd == null ? '0' : nFormatter(stock.currency_24h_volume_usd, 2),
currency_market_cap_usd: stock.currency_market_cap_usd == null ? '0' : nFormatter(stock.currency_market_cap_usd, 2),
DirectionClass: stock.currency_change_24h_usd === 0 ? 'nochange' : stock.currency_change_24h_usd >= 0 ? 'green' : 'red'
});
}
function nFormatter(num, digits) {
var si = [
{ value: 1, symbol: "" },
{ value: 1E3, symbol: "K" },
{ value: 1E6, symbol: "M" },
{ value: 1E9, symbol: "B" },
{ value: 1E12, symbol: "T" },
{ value: 1E15, symbol: "P" },
{ value: 1E18, symbol: "E" }
];
var rx = /\.0+$|(\.[0-9]*[1-9])0+$/;
var i;
for (i = si.length - 1; i > 0; i--) {
if (num >= si[i].value) {
break;
}
}
return (num / si[i].value).toFixed(digits).replace(rx, "$1") + si[i].symbol;
}
function formatprices(n, curr) {
var sep = sep || ".";
var decimals;
if (n > 0.99999999) {
decimals = decimals || 2;
}
else {
decimals = decimals || 6;
}
return n.toLocaleString().split(sep)[0]
+ sep
+ n.toFixed(decimals).split(sep)[1];
}
$.extend(ticker.client, {
updateStockPrice: function (stock) {
var displayStock = formatStock(stock),
$tdprice = $(tdPrice.supplant(displayStock)),
$tdpercentage = $(tdPercentage.supplant(displayStock)),
$tdvolume = $(tdVolume.supplant(displayStock)),
$tdcap = $(tdMarketcap.supplant(displayStock));
if (stock.LastChange != 0.0) {
bgprice = stock.LastChange < 0.0
? '255,148,148'
: '154,240,117';
$stockTableBody.find('td[data-rank-price=' + stock.currency_query + ']').replaceWith($tdprice);
$tdpricespn = $stockTableBody.find('div[data-price-spn=' + stock.currency_query + ']');
$tdpricespn.flash(bgprice, 1500);
}
if (stock.LastChangePercentage != 0.0) {
bgper = stock.LastChangePercentage < 0.0
? '255,148,148'
: '154,240,117';
$stockTableBody.find('td[data-rank-perc=' + stock.currency_query + ']').replaceWith($tdpercentage);
$tdpercentagespn = $stockTableBody.find('div[data-change-spn=' + stock.currency_query + ']');
$tdpercentagespn.flash(bgper, 1500);
}
if (stock.LastChangeVolume != 0.0) {
bgvol = stock.LastChangeVolume < 0.0
? '255,148,148'
: '154,240,117';
$stockTableBody.find('td[data-rank-volume=' + stock.currency_query + ']').replaceWith($tdvolume);
$tdvolumespn = $stockTableBody.find('div[data-24-volume-spn=' + stock.currency_query + ']');
$tdvolumespn.flash(bgvol, 1500);
}
if (stock.LastChangeCap != 0.0) {
bgcap = stock.LastChangeCap < 0.0
? '255,148,148'
: '154,240,117';
$stockTableBody.find('td[data-rank-cap=' + stock.currency_query + ']').replaceWith($tdcap);
$tdcapspn = $stockTableBody.find('div[data-mcap-spn=' + stock.currency_query + ']');
$tdcapspn.flash(bgcap, 1500);
}
}
});
$.connection.hub.url = 'http://localhost:13429/signalr';
$.connection.hub.qs = { 'page_no': $("#page").val() };
$.connection.hub.start().done(function () {
console.log("connected");
}).then(function () {
return ticker.server.openMarket();
});
});
Looking at your code, your global variable pageno is always the last page that was requested:
public void OpenMarket(int page_no)
{
pageno = page_no;
_timer = new Timer(UpdateStockPrices, pageno, _updateInterval, _updateInterval);
}
You need another variable that tracks the max page.
public volatile int pageMax;
public void OpenMarket(int page_no)
{
pageno = page_no;
pageMax = pageno > pageMax
: pageno
? pageMax;
_timer = new Timer(UpdateStockPrices, pageno, _updateInterval, _updateInterval);
}
Then make sure to broadcast the correct stocks to the pages.
I am trying to query data from orientdb while ignoring some edges.
My query has the form:
select expand(dijkstra(#12:15,#12:20,'property','both'))
but as mentioned I want to ignore some edges of the graph.
Are there any suggestions?
Edit
Here is my graph structure .
Station as Vertex
Image Click
Path as Edge
Image Click
Thank you #Ivan Mainetti so much for answer i have try the testing main()
Here is my main()
String nomeDb = "Demo2";
try {
System.out.println("Before connect OServerAdmin");
OServerAdmin serverAdmin = new OServerAdmin("remote:128.199.xxx.xxx/"+nomeDb).connect("admin","password");
System.out.println("After connect");
if(serverAdmin.existsDatabase()){ // il db esiste
System.out.println("in if");
//connessione a db
OrientGraph g = new OrientGraph("remote:128.199.xxx.xxx/"+nomeDb);
DijkstraExcl d = new DijkstraExcl(g, "Path", "distance");
Set<String> ex =new HashSet<String>();
//------------------------------------------------
Vertex start = g.getVertex("#12:6");
Vertex end = g.getVertex("#12:11");
ex.add("#13:0");
Direction direction = Direction.OUT;
System.out.println(d.getPath(start,end,direction,ex));
System.out.println(d.getPathString(start,end,direction,ex));
System.out.println(d.getWeight(start,end,direction,ex));
//------------------------------------------------
//chiude db
g.shutdown();
}
else{
System.out.println("Il database '"+ nomeDb + "' non esiste");
}
serverAdmin.close();
} catch (IOException e) {
e.printStackTrace();
}
and the result after run the main() is
null
null
2147483647
The correct answer after ignore [#13:0] should be
[#12:6,#12:8,#12:10,#12:11]
Try the following JS function that has as parameters ridFrom, ridTo, property, direction and excludeEdges.
With Studio you can try it with this command:
select expand(result) from (select myFunction("12:6","12:11","distance","out","[#13:0]") as result)
The edges "edge1" and "edge2" are ignored.
var g=orient.getGraph();
var listEdges=excludeEdges.substring(1,excludeEdges.length-1).split(",");
var S=[], T=[] , id_weigth=[] , from , to , infinity = Number.MAX_VALUE;
step1();
step2();
return getPath();
// Initialization
function step1() {
var selectFrom=g.command("sql","select from V where #rid ="+ ridFrom);
var selectTo=g.command("sql","select from V where #rid ="+ ridTo);
if(selectFrom.length>0 && selectTo.length>0){
from=selectFrom[0];
to=selectTo[0];
S.push(from);
var selectAll=g.command("sql","select from V");
for (i=0;i<selectAll.length;i++) {
if (selectAll[i].getId()!=from.getId())
T.push(selectAll[i]);
}
var index=1;
for (i=0;i<selectAll.length;i++) {
var id = selectAll[i].getId();
if (selectAll[i].getId()!= from.getId()) {
id_weigth[index] = {id:id,weigth:infinity};
index++;
}
else
id_weigth[0] = {id:id,weigth:0};
}
setWeigth_Direction(from);
}
}
// Assignment permanent label
function step2(){
var stop = true;
do {
stop = true;
for (i=0;i<T.length;i++) {
var id = T[i].getId();
for (j=0;j<id_weigth.length;j++) {
if (id_weigth[j].id==id) {
if (id_weigth[j].weigth != infinity){
stop = false;
}
}
}
}
if (stop == true)
break;
else {
var index2 = 0; minWeigth = 0; j = null;
for (i=0;i<T.length;i++) {
var id = T[i].getId();
for (m=0;m<id_weigth.length;m++) {
if (id_weigth[m].id==id) {
if (index2 == 0) {
minWeigth = id_weigth[m].weigth;
index2++;
j = T[i];
}
else if (id_weigth[m].weigth < minWeigth) {
minWeigth = id_weigth[m].weigth;
j = T[i];
}
}
}
}
T.splice(getPositionInT(j.getId()),1);
S.push(j);
if (T.length == 0)
break;
else
step3(j);
}
} while (stop == false);
}
// Assignment temporary label
function step3(j) {
setWeigth_Direction(j);
}
function setWeigth(vertex,direction1,direction2) {
var edges=g.command("sql","select expand(" + direction1+"E()) from "+ vertex.getId());
for(m=0;m<edges.length;m++){
var myEdge=edges[m];;
var idEdge = myEdge.getId().toString();
var validEdge=true;
for (s=0;s<listEdges.length;s++) {
if(listEdges[s]==idEdge)
validEdge=false;
}
if(validEdge==true){
var myWeigth = myEdge.getProperty(property);
var myVertex=g.command("sql","select expand("+ direction2 + ") from " +myEdge.getId());
var id = myVertex[0].getId();
if(vertex!=from){
for (p=0;p<T.length;p++) {
if (T[p].getId()==id) {
var id_weight_i = getId_Weigth(id);
var id_weight_j = getId_Weigth(j.getId());
var weigthi = id_weight_i.weigth;
var weigthj = id_weight_j.weigth;
if (weigthi > weigthj + myWeigth) {
id_weight_i.weigth=weigthj + myWeigth;
id_weight_i.previous=vertex;
}
}
}
}
else{
for (q=0;q<id_weigth.length;q++) {
if (id_weigth[q].id==id) {
id_weigth[q].weigth=myWeigth;
id_weigth[q].previous=vertex;
}
}
}
}
}
}
function getId_Weigth(id) {
for (l=0;l<id_weigth.length;l++) {
if (id_weigth[l].id==id)
return id_weigth[l];
}
return null;
}
function getPath(){
var validPath = true, temp = [], path = [];
temp.push(to);
var npm = getId_Weigth(to.getId());
var v = npm.previous;
while (v != from) {
temp.push(v);
if (v == null) {
validPath = false;
break;
}
npm = getId_Weigth(v.getId());
v = npm.previous;
}
if (validPath == true) {
temp.push(from);
for (i = temp.length - 1; i >= 0; i--)
path.push(temp[i]);
}
return path;
}
function setWeigth_Direction(vertex){
if (direction == "both"){
setWeigth(vertex,"in","out");
setWeigth(vertex,"out","in");
}
else if (direction == "in")
setWeigth(vertex,"in","out");
else
setWeigth(vertex,"out","in");
}
function getPositionInT(id){
for (l=0;l<T.length;l++) {
if(T[l].getId()==id)
return l;
}
return null;
}
I created this class that find the dijkstra path including the option of excluding a specific list of edges by rid number.
DijkstraExcl.java
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import com.tinkerpop.blueprints.Direction;
import com.tinkerpop.blueprints.Edge;
import com.tinkerpop.blueprints.Vertex;
import com.tinkerpop.blueprints.impls.orient.OrientGraph;
public class DijkstraExcl {
private OrientGraph g; //grafh DB
private Set<String> S; //visited rids
private Set<String> T; //to visit rids
private Map<String,Integer> f; //f(i) < #rid, weight_to_get_to_#rid >
private Map<String,String> J; //J(i) < #rid, previous_node_in_the_shortest_path >
private String eClass; //edge class to use
private String prop; //weight property to use on the edge
public DijkstraExcl(OrientGraph g, String e, String p){
this.g= g;
this.eClass = e;
this.prop = p;
S = new HashSet<String>();
T = new HashSet<String>();
f = new HashMap<String,Integer>();
J = new HashMap<String,String>();
}
//private methods
// (Vertex start_vertex, Vertex dest_vertex, Direction.IN/OUT/BOTH, Set of edge rids to exclude)
private void findPath(Vertex startV, Vertex endV, Direction dir, Set<String> excludeEdgeRids){
//init
S.clear();
T.clear();
f.clear();
J.clear();
//step1
Iterator<Vertex> vertici = g.getVertices().iterator();
while(vertici.hasNext()){
Vertex ver = vertici.next();
f.put(ver.getId().toString(), Integer.MAX_VALUE);
T.add(ver.getId().toString());
}
f.put(startV.getId().toString(), 0); //f(startV) = 0
J.put(startV.getId().toString(), null); //J(startV) = null
T.remove(startV.getId().toString()); //startV visited => removed from T
S.add(startV.getId().toString()); // and added in S
Iterator<Vertex> near = startV.getVertices(dir, eClass).iterator();
while(near.hasNext()){
Vertex vicino = near.next();
J.put(vicino.getId().toString(), startV.getId().toString()); //J(i) = startV
f.put(vicino.getId().toString(), weight(startV.getId().toString(), vicino.getId().toString(),dir,excludeEdgeRids)); //f(i) = weight(startV, i)
}
//step2
Boolean cont = false;
Iterator<String> t = T.iterator();
while(t.hasNext()){
String i = t.next();
if(f.get(i)!=Integer.MAX_VALUE){
cont = true;
}
}
while(cont){
String j = startV.getId().toString();
Integer ff = Integer.MAX_VALUE;
t = T.iterator();
while(t.hasNext()){
String i = t.next();
if(f.get(i)<=ff){
ff = f.get(i);
j = i;
}
}
T.remove(j);
S.add(j);
if(T.isEmpty()){
break;
}
//step3
near = g.getVertex(j).getVertices(dir, eClass).iterator();
while(near.hasNext()){
Vertex vic = near.next();
String i = vic.getId().toString();
if( (T.contains(i)) && (f.get(i) > (f.get(j) + weight(j,i,dir,excludeEdgeRids))) ){
if(weight(j,i,dir,excludeEdgeRids)==Integer.MAX_VALUE){
f.put(i, Integer.MAX_VALUE);
}else{
f.put(i, (f.get(j) + weight(j,i,dir,excludeEdgeRids)));
}
J.put(i, j);
}
}
//shall we continue?
cont = false;
t = T.iterator();
while(t.hasNext()){
String i = t.next();
if(f.get(i)!=Integer.MAX_VALUE){
cont = true;
}
}
}
}
private int weight(String rid_a, String rid_b, Direction dir, Set<String> excl){ //in case of multiple/duplicate edges return the lightest
Integer d = Integer.MAX_VALUE;
Integer dd;
rid_b = "v["+rid_b+"]";
if(excl==null){
excl = new HashSet<String>();
}
Vertex a = g.getVertex(rid_a);
Iterator<Edge> eS = a.getEdges(dir, eClass).iterator();
Set<Edge> goodEdges = new HashSet<Edge>();
while(eS.hasNext()){
Edge e = eS.next();
if((e.getProperty("out").toString().equals(rid_b) || e.getProperty("in").toString().equals(rid_b)) && !excl.contains(e.getId().toString())){
goodEdges.add(e);
}
}
Iterator<Edge> edges= goodEdges.iterator();
while(edges.hasNext()){
Edge e=edges.next();
dd = e.getProperty(prop);
if(dd<d){
d=dd;
}
}
return d;
}
//public methods
public List<Vertex> getPath (Vertex startV, Vertex endV, Direction dir, Set<String> exclECl){
String j,i;
List<Vertex> ppp = new ArrayList<Vertex>();
List<Vertex> path = new ArrayList<Vertex>();
findPath(startV, endV, dir, exclECl);
i = endV.getId().toString();
path.add(endV);
if(f.get(endV.getId().toString()) == Integer.MAX_VALUE){
return null;
}
while(!i.equals(startV.getId().toString())){
j = J.get(i);
if(j == null){
return null;
}
path.add(g.getVertex(j));
i = j;
}
for(int a=0, b=path.size()-1;a<path.size();a++, b--){
ppp.add(a, path.get(b));
}
return ppp;
}
public List<String> getPathString (Vertex startV, Vertex endV, Direction dir, Set<String> exclECl){
List<String> pathS = new ArrayList<String>();
List<Vertex> path = getPath(startV, endV, dir, exclECl);
if(path == null){
return null;
}
for(Vertex v : path){
pathS.add(v.getId().toString());
}
return pathS;
}
public Integer getWeight(Vertex startV, Vertex endV, Direction dir, Set<String> exclECl){
findPath(startV, endV, dir,exclECl);
return f.get(endV.getId().toString());
}
}
and hers's a testing main:
public class test_dijkstra {
public static void main(String[] args) {
String nomeDb = "dijkstra_test";
try {
OServerAdmin serverAdmin = new OServerAdmin("remote:localhost/"+nomeDb).connect("root", "root");
if(serverAdmin.existsDatabase()){ // il db esiste
//connessione a db
OrientGraph g = new OrientGraph("remote:localhost/"+nomeDb);
DijkstraExcl d = new DijkstraExcl(g, "arco", "peso");
Set<String> ex =new HashSet<String>();
//------------------------------------------------
Vertex start = g.getVertex("#9:0");
Vertex end = g.getVertex("#9:5");
ex.add("#12:4");
Direction direction = Direction.BOTH;
System.out.println(d.getPath(start,end,direction,ex));
System.out.println(d.getPathString(start,end,direction,ex));
System.out.println(d.getWeight(start,end,direction,ex));
//------------------------------------------------
//chiude db
g.shutdown();
}
else{
System.out.println("Il database '"+ nomeDb + "' non esiste");
}
serverAdmin.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
and its output:
[v[#9:0], v[#9:1], v[#9:2], v[#9:4], v[#9:5]]
[#9:0, #9:1, #9:2, #9:4, #9:5]
10
Here's the structure of my test db:
One approach would be to use the fact that OrientDB has some support for "Infinity", as illustrated by this "console.sh" typescript:
> select 1.0E400
----+------+--------
# |#CLASS|1
----+------+--------
0 |null |Infinity
----+------+--------
> select eval('0 < 1.0E400')
----+------+----
# |#CLASS|eval
----+------+----
0 |null |true
----+------+----
> select -1.0E400
----+------+---------
# |#CLASS|-1
----+------+---------
0 |null |-Infinity
----+------+---------
> select eval('0 < -1.0E400')
----+------+-----
# |#CLASS|eval
----+------+-----
0 |null |false
----+------+-----
How can I add a countdown in this script, by pressing the left mouse button? Every click counts minus 1. 10,9,8,7,6,5,4,3,2,1,0 example? This currently does not work in this script, and I do not understand the problem.
#pragma strict
var myTrigger : GameObject;
var myObject : GameObject;
var countAmmo : int = 10 ;
private var score : int = 10;
var guiScore : GUIText;
function Start ()
{
guiScore.text = "Score: 10";
}
function Update()
{
if(Input.GetButtonDown("Fire1"))
countAmmo = countAmmo -1;
score = countAmmo -1;
if(countAmmo == 0)
if(score == -1)
{
myObject.SetActive(false);
}
else
{
guiScore.text = "Score: -1";
myObject.SetActive(true);
}
}
I don't know exactly which language this is or in which context you are trying to achieve that, but looking at your code it seems that its only a problem with some brackets in your if-clauses. Try it, no guarantee that it's working.
#pragma strict
var myTrigger : GameObject;
var myObject : GameObject;
var countAmmo : int = 10 ;
private var score : int = 10;
var guiScore : GUIText;
function Start ()
{
guiScore.text = "Score: 10";
}
function Update()
{
if(Input.GetButtonDown("Fire1"))
{
countAmmo = countAmmo -1;
score = countAmmo -1;
guiScore.text = "Score: " + score.ToString();
if(countAmmo <= 0)
{
if(score == -1)
{
myObject.SetActive(false);
} else {
guiScore.text = "Score: -1";
}
myObject.SetActive(true);
}
}
}
This line:
guiScore.text = "Score: -1";
Should be:
guiScore.text = "Score:" + score;
#pragma strict
var myTrigger : GameObject;
var myObject : GameObject;
var countAmmo : int = 10 ;
private var score : int = 10;
var guiScore : GUIText;
function Start ()
{
guiScore.text = "Score: " + score.toString();
}
function Update()
{
if(Input.GetButtonDown("Fire1"))
countAmmo--;
score = countAmmo - 1;
if(countAmmo == 0)
{
if(score == -1)
{
myObject.SetActive(false);
}
else
{
guiScore.text = "Score: " + score.ToString();
myObject.SetActive(true);
}
}
}
Hi i want to remove all the test results which were skipped in test execution from appearing in the HTML report which testng generates. Any idea how can i achieve that. I know that there is IReporter which could be used as listener to generate reports. but then i only want to modify the Reports generated by testng. I do not want to generate my own reports. Any idea how i can achieve it. TIA!!!
import java.util.List;
import org.testng.IReporter;
import org.testng.ISuite;
import org.testng.xml.XmlSuite;
public class ReporterListener implements IReporter {
#Override
public void generateReport(List<XmlSuite> xmlSuites, List<ISuite> suites,
String outputDirectory)
{
//What code should come here....
}
}
I think you can achieve this only by customizing the TestNG report. I have done this for one of my requirements. Here is the code for the customReport. In the generateSuiteSummaryReport(suites), generateMethodSummaryReport(suites) you can stop the Skipped tests logic. Just have this class extend the ReporterListener.
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.io.PrintWriter;
import java.text.DecimalFormat;
import java.text.NumberFormat;
import java.util.Arrays;
import java.util.Collection;
import java.util.Comparator;
import java.util.List;
import java.util.Map;
import java.util.Scanner;
import java.util.Set;
import org.testng.IInvokedMethod;
import org.testng.IResultMap;
import org.testng.ISuite;
import org.testng.ISuiteResult;
import org.testng.ITestClass;
import org.testng.ITestContext;
import org.testng.ITestNGMethod;
import org.testng.ITestResult;
import org.testng.Reporter;
import org.testng.collections.Lists;
import org.testng.internal.Utils;
import org.testng.log4testng.Logger;
import org.testng.xml.XmlSuite;
/**
* Reporter that generates a single-page HTML report of the test results.
* <p>
* Based on an earlier implementation by Paul Mendelson.
* </p>
*
* #author Abraham Lin
*/
public class CustomReport extends CustomReportListener {
private static final Logger LOG = Logger.getLogger(CustomReport.class);
// ~ Instance fields ------------------------------------------------------
private PrintWriter m_out;
private int m_row;
private Integer m_testIndex;
private int m_methodIndex;
private Scanner scanner;
// ~ Methods --------------------------------------------------------------
/** Creates summary of the run */
#Override
public void generateReport(List<XmlSuite> xml, List<ISuite> suites,
String outdir) {
try {
m_out = createWriter(outdir);
} catch (IOException e) {
LOG.error("output file", e);
return;
}
startHtml(m_out);
generateSuiteSummaryReport(suites);
generateMethodSummaryReport(suites);
generateMethodDetailReport(suites);
endHtml(m_out);
m_out.flush();
m_out.close();
}
protected PrintWriter createWriter(String outdir) throws IOException {
new File(outdir).mkdirs();
return new PrintWriter(new BufferedWriter(new FileWriter(new File(
outdir, "BANC Selenium RC Execution Report.html"))));
}
/**
* Creates a table showing the highlights of each test method with links to
* the method details
*/
protected void generateMethodSummaryReport(List<ISuite> suites) {
m_methodIndex = 0;
startResultSummaryTable("methodOverview");
int testIndex = 1;
for (ISuite suite : suites) {
if (suites.size() > 1) {
titleRow(suite.getName(), 5);
}
Map<String, ISuiteResult> r = suite.getResults();
for (ISuiteResult r2 : r.values()) {
ITestContext testContext = r2.getTestContext();
String testName = testContext.getName();
m_testIndex = testIndex;
resultSummary(suite, testContext.getFailedConfigurations(),
testName, "failed", " (configuration methods)");
resultSummary(suite, testContext.getFailedTests(), testName,
"failed", "");
resultSummary(suite, testContext.getSkippedConfigurations(),
testName, "skipped", " (configuration methods)");
resultSummary(suite, testContext.getSkippedTests(), testName,
"skipped", "");
resultSummary(suite, testContext.getPassedTests(), testName,
"passed", "");
testIndex++;
}
}
m_out.println("</table>");
}
/** Creates a section showing known results for each method */
protected void generateMethodDetailReport(List<ISuite> suites) {
m_methodIndex = 0;
for (ISuite suite : suites) {
Map<String, ISuiteResult> r = suite.getResults();
for (ISuiteResult r2 : r.values()) {
ITestContext testContext = r2.getTestContext();
if (r.values().size() > 0) {
m_out.println("<h1>" + testContext.getName() + "</h1>");
}
resultDetail(testContext.getFailedConfigurations());
resultDetail(testContext.getFailedTests());
resultDetail(testContext.getSkippedConfigurations());
resultDetail(testContext.getSkippedTests());
resultDetail(testContext.getPassedTests());
}
}
}
/**
* #param tests
*/
private void resultSummary(ISuite suite, IResultMap tests, String testname,
String style, String details) {
if (tests.getAllResults().size() > 0) {
StringBuffer buff = new StringBuffer();
String lastClassName = "";
int mq = 0;
int cq = 0;
for (ITestNGMethod method : getMethodSet(tests, suite)) {
m_row += 1;
m_methodIndex += 1;
ITestClass testClass = method.getTestClass();
String className = testClass.getName();
if (mq == 0) {
String id = (m_testIndex == null ? null : "t"
+ Integer.toString(m_testIndex));
titleRow(testname + " — " + style + details, 5, id);
m_testIndex = null;
}
if (!className.equalsIgnoreCase(lastClassName)) {
if (mq > 0) {
cq += 1;
m_out.print("<tr class=\"" + style
+ (cq % 2 == 0 ? "even" : "odd") + "\">"
+ "<td");
if (mq > 1) {
m_out.print(" rowspan=\"" + mq + "\"");
}
m_out.println(">" + lastClassName + "</td>" + buff);
}
mq = 0;
buff.setLength(0);
lastClassName = className;
}
Set<ITestResult> resultSet = tests.getResults(method);
long end = Long.MIN_VALUE;
long start = Long.MAX_VALUE;
for (ITestResult testResult : tests.getResults(method)) {
if (testResult.getEndMillis() > end) {
end = testResult.getEndMillis();
}
if (testResult.getStartMillis() < start) {
start = testResult.getStartMillis();
}
}
mq += 1;
if (mq > 1) {
buff.append("<tr class=\"" + style
+ (cq % 2 == 0 ? "odd" : "even") + "\">");
}
String description = method.getDescription();
String testInstanceName = resultSet
.toArray(new ITestResult[] {})[0].getTestName();
buff.append("<td><a href=\"#m"
+ m_methodIndex
+ "\">"
+ qualifiedName(method)
+ " "
+ (description != null && description.length() > 0 ? "(\""
+ description + "\")"
: "")
+ "</a>"
+ (null == testInstanceName ? "" : "<br>("
+ testInstanceName + ")") + "</td>"
+ "<td class=\"numi\">" + resultSet.size() + "</td>"
+ "<td>" + start + "</td>" + "<td class=\"numi\">"
+ (end - start) + "</td>" + "</tr>");
}
if (mq > 0) {
cq += 1;
m_out.print("<tr class=\"" + style
+ (cq % 2 == 0 ? "even" : "odd") + "\">" + "<td");
if (mq > 1) {
m_out.print(" rowspan=\"" + mq + "\"");
}
m_out.println(">" + lastClassName + "</td>" + buff);
}
}
}
/** Starts and defines columns result summary table */
private void startResultSummaryTable(String style) {
tableStart(style, "summary");
m_out.println("<tr><th>Class</th>"
+ "<th>Method</th><th># of<br/>Scenarios</th><th>Start</th><th>Time<br/>(ms)</th></tr>");
m_row = 0;
}
private String qualifiedName(ITestNGMethod method) {
StringBuilder addon = new StringBuilder();
String[] groups = method.getGroups();
int length = groups.length;
if (length > 0 && !"basic".equalsIgnoreCase(groups[0])) {
addon.append("(");
for (int i = 0; i < length; i++) {
if (i > 0) {
addon.append(", ");
}
addon.append(groups[i]);
}
addon.append(")");
}
return "<b>" + method.getMethodName() + "</b> " + addon;
}
private void resultDetail(IResultMap tests) {
for (ITestResult result : tests.getAllResults()) {
ITestNGMethod method = result.getMethod();
m_methodIndex++;
String cname = method.getTestClass().getName();
m_out.println("<h2 id=\"m" + m_methodIndex + "\">" + cname + ":"
+ method.getMethodName() + "</h2>");
Set<ITestResult> resultSet = tests.getResults(method);
generateForResult(result, method, resultSet.size());
m_out.println("<p class=\"totop\">back to summary</p>");
}
}
/**
* Write the first line of the stack trace
*
* #param tests
*/
private void getShortException(IResultMap tests) {
for (ITestResult result : tests.getAllResults()) {
m_methodIndex++;
Throwable exception = result.getThrowable();
List<String> msgs = Reporter.getOutput(result);
boolean hasReporterOutput = msgs.size() > 0;
boolean hasThrowable = exception != null;
if (hasThrowable) {
boolean wantsMinimalOutput = result.getStatus() == ITestResult.SUCCESS;
if (hasReporterOutput) {
m_out.print("<h3>"
+ (wantsMinimalOutput ? "Expected Exception"
: "Failure") + "</h3>");
}
// Getting first line of the stack trace
String str = Utils.stackTrace(exception, true)[0];
scanner = new Scanner(str);
String firstLine = scanner.nextLine();
m_out.println(firstLine);
}
}
}
/**
* Write all parameters
*
* #param tests
*/
private void getParameters(IResultMap tests) {
for (ITestResult result : tests.getAllResults()) {
m_methodIndex++;
Object[] parameters = result.getParameters();
boolean hasParameters = parameters != null && parameters.length > 0;
if (hasParameters) {
for (Object p : parameters) {
m_out.println(Utils.escapeHtml(org.testng.internal.Utils
.toString(p, String.class)) + " | ");
}
}
}
}
private void generateForResult(ITestResult ans, ITestNGMethod method,
int resultSetSize) {
Object[] parameters = ans.getParameters();
boolean hasParameters = parameters != null && parameters.length > 0;
if (hasParameters) {
tableStart("result", null);
m_out.print("<tr class=\"param\">");
for (int x = 1; x <= parameters.length; x++) {
m_out.print("<th>Param." + x + "</th>");
}
m_out.println("</tr>");
m_out.print("<tr class=\"param stripe\">");
for (Object p : parameters) {
m_out.println("<td>"
+ Utils.escapeHtml(Utils.toString(p, String.class))
+ "</td>");
}
m_out.println("</tr>");
}
List<String> msgs = Reporter.getOutput(ans);
boolean hasReporterOutput = msgs.size() > 0;
Throwable exception = ans.getThrowable();
boolean hasThrowable = exception != null;
if (hasReporterOutput || hasThrowable) {
if (hasParameters) {
m_out.print("<tr><td");
if (parameters.length > 1) {
m_out.print(" colspan=\"" + parameters.length + "\"");
}
m_out.println(">");
} else {
m_out.println("<div>");
}
if (hasReporterOutput) {
if (hasThrowable) {
m_out.println("<h3>Test Messages</h3>");
}
for (String line : msgs) {
m_out.println(line + "<br/>");
}
}
if (hasThrowable) {
boolean wantsMinimalOutput = ans.getStatus() == ITestResult.SUCCESS;
if (hasReporterOutput) {
m_out.println("<h3>"
+ (wantsMinimalOutput ? "Expected Exception"
: "Failure") + "</h3>");
}
generateExceptionReport(exception, method);
}
if (hasParameters) {
m_out.println("</td></tr>");
} else {
m_out.println("</div>");
}
}
if (hasParameters) {
m_out.println("</table>");
}
}
protected void generateExceptionReport(Throwable exception,
ITestNGMethod method) {
m_out.print("<div class=\"stacktrace\">");
m_out.print(Utils.stackTrace(exception, true)[0]);
m_out.println("</div>");
}
/**
* Since the methods will be sorted chronologically, we want to return the
* ITestNGMethod from the invoked methods.
*/
private Collection<ITestNGMethod> getMethodSet(IResultMap tests,
ISuite suite) {
List<IInvokedMethod> r = Lists.newArrayList();
List<IInvokedMethod> invokedMethods = suite.getAllInvokedMethods();
for (IInvokedMethod im : invokedMethods) {
if (tests.getAllMethods().contains(im.getTestMethod())) {
r.add(im);
}
}
Arrays.sort(r.toArray(new IInvokedMethod[r.size()]), new TestSorter());
List<ITestNGMethod> result = Lists.newArrayList();
// Add all the invoked methods
for (IInvokedMethod m : r) {
result.add(m.getTestMethod());
}
// Add all the methods that weren't invoked (e.g. skipped) that we
// haven't added yet
for (ITestNGMethod m : tests.getAllMethods()) {
if (!result.contains(m)) {
result.add(m);
}
}
return result;
}
#SuppressWarnings("unused")
public void generateSuiteSummaryReport(List<ISuite> suites) {
printExecutionParameters();
m_out.println("<b align=\"center\">Execution Summary</b>");
tableStart("testOverview", null);
m_out.print("<tr>");
tableColumnStart("Test");
tableColumnStart("Methods<br/>Passed");
tableColumnStart("Scenarios<br/>Passed");
tableColumnStart("# skipped");
tableColumnStart("# failed");
tableColumnStart("Total<br/>Time");
tableColumnStart("Included<br/>Groups");
tableColumnStart("Excluded<br/>Groups");
m_out.println("</tr>");
NumberFormat formatter = new DecimalFormat("#,##0.0");
int qty_tests = 0;
int qty_pass_m = 0;
int qty_pass_s = 0;
int qty_skip = 0;
int qty_fail = 0;
long time_start = Long.MAX_VALUE;
long time_end = Long.MIN_VALUE;
m_testIndex = 1;
for (ISuite suite : suites) {
if (suites.size() > 1) {
titleRow(suite.getName(), 8);
}
Map<String, ISuiteResult> tests = suite.getResults();
for (ISuiteResult r : tests.values()) {
qty_tests += 1;
ITestContext overview = r.getTestContext();
startSummaryRow(overview.getName());
int q = getMethodSet(overview.getPassedTests(), suite).size();
qty_pass_m += q;
summaryCell(q, Integer.MAX_VALUE);
q = overview.getPassedTests().size();
qty_pass_s += q;
summaryCell(q, Integer.MAX_VALUE);
q = getMethodSet(overview.getSkippedTests(), suite).size();
qty_skip += q;
summaryCell(q, 0);
q = getMethodSet(overview.getFailedTests(), suite).size();
qty_fail += q;
summaryCell(q, 0);
time_start = Math.min(overview.getStartDate().getTime(),
time_start);
time_end = Math.max(overview.getEndDate().getTime(), time_end);
summaryCell(
formatter.format((overview.getEndDate().getTime() - overview
.getStartDate().getTime()) / 1000.)
+ " seconds", true);
summaryCell(overview.getIncludedGroups());
summaryCell(overview.getExcludedGroups());
m_out.println("</tr>");
m_testIndex++;
}
}
if (qty_tests > 1) {
m_out.println("<tr class=\"total\"><td>Total</td>");
summaryCell(qty_pass_m, Integer.MAX_VALUE);
summaryCell(qty_pass_s, Integer.MAX_VALUE);
summaryCell(qty_skip, 0);
summaryCell(qty_fail, 0);
summaryCell(formatter.format((time_end - time_start) / 1000.)
+ " seconds", true);
m_out.println("<td colspan=\"2\"> </td></tr>");
}
m_out.println("</table>");
m_out.println("<p></p>");
}
private void printExecutionParameters() {
m_out.println("<b>Execution Parameters</b>");
tableStart("testOverview", null);
m_out.print("<tr>");
tableColumnStart("AppicationURL");
tableColumnStart("AppUserName|Password");
tableColumnStart("DatabaseURL");
tableColumnStart("DBUserName|Password");
m_out.println("</tr>");
summaryCell(applicationURL, true);
summaryCell(applicationUserID + "|" + applicationPassword, true);
summaryCell(databaseURL, true);
summaryCell(databaseUserID + "|" + databasePassword, true);
m_out.println("</table>");
m_out.println("<p></p>");
}
private void summaryCell(String[] val) {
StringBuffer b = new StringBuffer();
for (String v : val) {
b.append(v + " ");
}
summaryCell(b.toString(), true);
}
private void summaryCell(String v, boolean isgood) {
m_out.print("<td class=\"numi" + (isgood ? "" : "_attn") + "\">" + v
+ "</td>");
}
private void startSummaryRow(String label) {
m_row += 1;
m_out.print("<tr"
+ (m_row % 2 == 0 ? " class=\"stripe\"" : "")
+ "><td style=\"text-align:left;padding-right:2em\"><a href=\"#t"
+ m_testIndex + "\">" + label + "</a>" + "</td>");
}
private void summaryCell(int v, int maxexpected) {
summaryCell(String.valueOf(v), v <= maxexpected);
}
private void tableStart(String cssclass, String id) {
m_out.println("<table cellspacing=\"0\" cellpadding=\"0\""
+ (cssclass != null ? " class=\"" + cssclass + "\""
: " style=\"padding-bottom:2em\"")
+ (id != null ? " id=\"" + id + "\"" : "") + ">");
m_row = 0;
}
private void tableColumnStart(String label) {
m_out.print("<th>" + label + "</th>");
}
private void titleRow(String label, int cq) {
titleRow(label, cq, null);
}
private void titleRow(String label, int cq, String id) {
m_out.print("<tr");
if (id != null) {
m_out.print(" id=\"" + id + "\"");
}
m_out.println("><th colspan=\"" + cq + "\">" + label + "</th></tr>");
m_row = 0;
}
/** Starts HTML stream */
protected void startHtml(PrintWriter out) {
out.println("<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.1//EN\" \"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd\">");
out.println("<html xmlns=\"http://www.w3.org/1999/xhtml\">");
out.println("<head>");
out.println("<title>BANC Selenium RC Execution Report</title>");
out.println("<style type=\"text/css\">");
out.println("table {margin-bottom:10px;border-collapse:collapse;empty-cells:show}");
out.println("td,th {border:1px solid #009;padding:.25em .5em}");
out.println(".result th {vertical-align:bottom}");
out.println(".param th {padding-left:1em;padding-right:1em}");
out.println(".param td {padding-left:.5em;padding-right:2em}");
out.println(".stripe td,.stripe th {background-color: #E6EBF9}");
out.println(".numi,.numi_attn {text-align:right}");
out.println(".total td {font-weight:bold}");
out.println(".passedodd td {background-color: #0A0}");
out.println(".passedeven td {background-color: #3F3}");
out.println(".skippedodd td {background-color: #CCC}");
out.println(".skippedodd td {background-color: #DDD}");
out.println(".failedodd td,.numi_attn {background-color: #F33}");
out.println(".failedeven td,.stripe .numi_attn {background-color: #D00}");
out.println(".stacktrace {white-space:pre;font-family:monospace}");
out.println(".totop {font-size:85%;text-align:center;border-bottom:2px solid #000}");
out.println("</style>");
out.println("</head>");
out.println("<body>");
}
/** Finishes HTML stream */
protected void endHtml(PrintWriter out) {
out.println("<center> Customized TestNG Report </center>");
out.println("</body></html>");
}
// ~ Inner Classes --------------------------------------------------------
/** Arranges methods by classname and method name */
private class TestSorter implements Comparator<IInvokedMethod> {
// ~ Methods
// -------------------------------------------------------------
/** Arranges methods by classname and method name */
#Override
public int compare(IInvokedMethod o1, IInvokedMethod o2) {
// System.out.println("Comparing " + o1.getMethodName() + " " +
// o1.getDate()
// + " and " + o2.getMethodName() + " " + o2.getDate());
return (int) (o1.getDate() - o2.getDate());
// int r = ((T) o1).getTestClass().getName().compareTo(((T)
// o2).getTestClass().getName());
// if (r == 0) {
// r = ((T) o1).getMethodName().compareTo(((T) o2).getMethodName());
// }
// return r;
}
}
}
What really happens to the currently executing request in IIS during a file upload, when the upload length exceed configured maxRequestLength.
Tried hard to find a decent article that talks about that, but there are none!!
Thanks
This is what exactly happens:
In class HttpRequest and in method GetEntireRawContent this condition is checked and will throw an exception:
if (length > maxRequestLengthBytes)
{
throw new HttpException(System.Web.SR.GetString("Max_request_length_exceeded"), null, 0xbbc);
}
Here is the whole of the method if you find useful:
private HttpRawUploadedContent GetEntireRawContent()
{
if (this._wr == null)
{
return null;
}
if (this._rawContent == null)
{
HttpRuntimeSection httpRuntime = RuntimeConfig.GetConfig(this._context).HttpRuntime;
int maxRequestLengthBytes = httpRuntime.MaxRequestLengthBytes;
if (this.ContentLength > maxRequestLengthBytes)
{
if (!(this._wr is IIS7WorkerRequest))
{
this.Response.CloseConnectionAfterError();
}
throw new HttpException(System.Web.SR.GetString("Max_request_length_exceeded"), null, 0xbbc);
}
int requestLengthDiskThresholdBytes = httpRuntime.RequestLengthDiskThresholdBytes;
HttpRawUploadedContent data = new HttpRawUploadedContent(requestLengthDiskThresholdBytes, this.ContentLength);
byte[] preloadedEntityBody = this._wr.GetPreloadedEntityBody();
if (preloadedEntityBody != null)
{
this._wr.UpdateRequestCounters(preloadedEntityBody.Length);
data.AddBytes(preloadedEntityBody, 0, preloadedEntityBody.Length);
}
if (!this._wr.IsEntireEntityBodyIsPreloaded())
{
int num3 = (this.ContentLength > 0) ? (this.ContentLength - data.Length) : 0x7fffffff;
HttpApplication applicationInstance = this._context.ApplicationInstance;
byte[] buffer = (applicationInstance != null) ? applicationInstance.EntityBuffer : new byte[0x2000];
int length = data.Length;
while (num3 > 0)
{
int size = buffer.Length;
if (size > num3)
{
size = num3;
}
int bytesIn = this._wr.ReadEntityBody(buffer, size);
if (bytesIn <= 0)
{
break;
}
this._wr.UpdateRequestCounters(bytesIn);
this.NeedToInsertEntityBody = true;
data.AddBytes(buffer, 0, bytesIn);
num3 -= bytesIn;
length += bytesIn;
if (length > maxRequestLengthBytes)
{
throw new HttpException(System.Web.SR.GetString("Max_request_length_exceeded"), null, 0xbbc);
}
}
}
data.DoneAddingBytes();
if ((this._installedFilter != null) && (data.Length > 0))
{
try
{
try
{
this._filterSource.SetContent(data);
HttpRawUploadedContent content2 = new HttpRawUploadedContent(requestLengthDiskThresholdBytes, data.Length);
HttpApplication application2 = this._context.ApplicationInstance;
byte[] buffer3 = (application2 != null) ? application2.EntityBuffer : new byte[0x2000];
while (true)
{
int num7 = this._installedFilter.Read(buffer3, 0, buffer3.Length);
if (num7 == 0)
{
break;
}
content2.AddBytes(buffer3, 0, num7);
}
content2.DoneAddingBytes();
data = content2;
}
finally
{
this._filterSource.SetContent(null);
}
}
catch
{
throw;
}
}
this._rawContent = data;
}
return this._rawContent;
}